设为首页 收藏本站
查看: 1765|回复: 0

[经验分享] 基于颜色模式的颜色条形码检测(使用python 2.7和opencv 2.2)

[复制链接]

尚未签到

发表于 2015-4-24 07:25:43 | 显示全部楼层 |阅读模式
  这种颜色条形码有3种颜色:青色,粉色和淡黄色。各种颜色区域为矩形,均匀分布在一个黑底的矩形中。
  检测的基本思想是:
  1) 如果某个像素属于3种颜色的一种,就把对应坐标处标记为1。
  处理完整幅图像后,得到一个2值图像。
  2)将1)中得到的2值图像分别向x和y轴投影,也即计算各行和各列的和。
  比如:一行为 101111,向y轴投影后,得到的值是5.
  投影后,得到x,y轴两个向量。
  3)在x和y轴向量中搜索最小和最大的非零值,对应的坐标就圈定了条形码所在位置。
  当然这里要设定一个阈值,比如非零值的最小必须大于3或者5之类的,因为矩形颜色块是有最小面积的。
  不过,为了能在实际中使用,还需要添加很多处理,比如噪声,颜色变化,视角变化之类的因素也需要考虑。
  下面是处理结果的截图,后面有代码:
  
  

DSC0000.gif DSC0001.gif 代码



#!/usr/bin/python
#
#

import cv
import sys
import math
names =  ["temp.jpg"];
def findFirstColorPattern(img, pattern):
    """
        try to test if one pixel is in our pattern
    """
    channels = [None, None, None]
    channels[0] = cv.CreateImage(cv.GetSize(img),8,1)#blue
    channels[1] = cv.CreateImage(cv.GetSize(img),8,1)#green
    channels[2] = cv.CreateImage(cv.GetSize(img),8,1)#red
    ch0 = cv.CreateImage(cv.GetSize(img),8,1)#blue
    ch1 = cv.CreateImage(cv.GetSize(img),8,1)#green
    ch2 = cv.CreateImage(cv.GetSize(img),8,1)#red
    cv.Split(img, ch0, ch1, ch2, None)
    dest0     = cv.CreateImage(cv.GetSize(img),8,1)
    dest1     = cv.CreateImage(cv.GetSize(img),8,1)
    dest2     = cv.CreateImage(cv.GetSize(img),8,1)
    dest3     = cv.CreateImage(cv.GetSize(img),8,1)
    cv.Smooth(ch0, channels[0], cv.CV_GAUSSIAN, 3, 3, 0)
    cv.Smooth(ch1, channels[1], cv.CV_GAUSSIAN, 3, 3, 0)
    cv.Smooth(ch2, channels[2], cv.CV_GAUSSIAN, 3, 3, 0)
    result  =[]
    for i in range(3):
        lower = pattern[2] - 25
        upper = pattern[2] + 25
        cv.InRangeS(channels[0],lower,upper,dest0)      
        lower = pattern[1] - 25
        upper = pattern[1] + 25
        cv.InRangeS(channels[1],lower,upper,dest1)
        lower = pattern[0] - 25
        upper = pattern[0] + 25        
        cv.InRangeS(channels[2],lower,upper,dest2)
        cv.And(dest0,dest1,dest3)
        temp    = cv.CreateImage(cv.GetSize(img),8,1)
        cv.And(dest2,dest3,temp)
        result.append(temp)
    cv.Or(result[0],result[1],dest0)
    cv.Or(dest0,result[2],dest3)
    cv.NamedWindow("result",cv.CV_WINDOW_AUTOSIZE)
    cv.ShowImage("result",dest3)
    #cv.WaitKey(0)
    return dest3
def xyProject(mat,imagesize):
    """
        "project" image to x and y axis
    """   
    colmask    =cv.CreateMat(imagesize[1],1,cv.CV_8UC1)
    rowmask    =cv.CreateMat(1,imagesize[0],cv.CV_8UC1)
    cv.Set(colmask,1)
    cv.Set(rowmask,1)
    colsum=[]
    for i in range(imagesize[0]):
        col = cv.GetCol(matrix,i)
        a = cv.DotProduct(colmask,col)
        colsum.append(a)
    rowsum =[]
    for i in range(imagesize[1]):
        row = cv.GetRow(matrix,i)
        a = cv.DotProduct(rowmask,row)
        rowsum.append(a)
    return (colsum,rowsum)
def getMinNonZero(arr):
    minv = max(arr)
    for a in arr:
        if a > 0 and a < minv:
            minv = a
    return minv
def getMeanDistance(data,minv):
    shiftindex = [0]
    index=[]
    for i in range(len(data)):
        if data>minv:
            index.append(i)
            shiftindex.append(i)
    index.append(index[len(index)-1])
    dist=[]
    for i in range(len(index)):
            dist.append(index-shiftindex)
    maxdist=max(dist)
    index=[]
    for i in dist:
        if i != maxdist and i > 1:
            index.append(i)
    mdist= sum(index)/len(index)
    #print mdist
    return mdist
if __name__ == "__main__":
    #TODO: robost against illumination change
    pattern_colors=[(219,235,102),(213,71,155),(67,170,228)]#pink, cyan, yellow
    image = cv.LoadImage(names[0])
    imagesize =cv.GetSize(image)
    matrix = findFirstColorPattern(image,pattern_colors)
    (colsum,rowsum) = xyProject(matrix,imagesize)
    # the following code is trying to find the edge of the small color rectangles
    rx0 = 0
    minv1 = getMinNonZero(colsum)
    for a in colsum:
        if a > minv1:
            break
        rx0 += 1
    minv2 = getMinNonZero(rowsum)
    ry0 = 0
    for a in rowsum:
        if a > minv2:
            break
        ry0 += 1
    arrlen = len(colsum)
    rx1 = arrlen -1
    for i in range(arrlen):
        if colsum[arrlen-1-i] > minv1:
            break
        rx1 -= 1
    arrlen = len(rowsum)
    ry1 = arrlen -1
    for i in range(arrlen):
        if rowsum[arrlen-1-i] > minv2:
            break
        ry1 -= 1
    # try to compute the mean distance between two small color rectangles
    mdist = getMeanDistance(colsum,minv1)
    rectx0 = rx0-mdist*2
    recty0 = ry0-mdist*2
    if rectx0 < 0:
        rectx0 = 0
    if recty0 < 0:
        recty0 = 0
    rectx1 = rx1+mdist*2
    if rectx1 > imagesize[0]:
        rectx1 = imagesize[0]
    recty1 = ry1+mdist*2
    if recty1 > imagesize[1]:
        recty1 = imagesize[1]
    #cv.Circle(image,(int(rx0),int(ry0)),5,cv.CV_RGB(0,255,0))
    #cv.Circle(image,(int(rx1),int(ry1)),5,cv.CV_RGB(0,255,0))
    roi = cv.GetSubRect(image,(rectx0,recty0,rectx1-rectx0,recty1-recty0))
    pt=[(rectx0,recty0),(rectx1,recty0),(rectx1,recty1),(rectx0,recty1)]
    cv.PolyLine( image, [pt], 1, cv.CV_RGB(0,255,0), 3, cv.CV_AA, 0 );
    cv.NamedWindow("test",cv.CV_WINDOW_AUTOSIZE)
    cv.ShowImage("test",image)
    cv.NamedWindow("roi",cv.CV_WINDOW_AUTOSIZE)
    cv.ShowImage("roi",roi)
    cv.SaveImage("result.png",image)
    cv.WaitKey(0)
    cv.DestroyWindow("test")
    cv.DestroyWindow("result")
    cv.DestroyWindow("roi")
  


  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-60081-1-1.html 上篇帖子: Java版的Python,Jython 下篇帖子: 用Python做GIS:翻炒篇
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表