美文网首页
2018-01-27 充值卡OCR的尝试

2018-01-27 充值卡OCR的尝试

作者: shanggl | 来源:发表于2018-01-27 21:18 被阅读0次

    充值卡上的卡号、密码是否OCR识别?我要尝试一下,今天记录第一步,图像分割,将数字分割出来。下一步是数字二次分割、训练、识别。

    充值卡的图是这样的:

    chongzhika.jpg

    直接上代码,注释中解释处理过程。

    
    import cv2
    import imutils
    from imutils import contours
    import numpy as np
    
    
    #open convert to gray  打开图片,转换为灰度图 
    img=cv2.imread("chongzhika.jpg")
    bimg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
    #cv2 里面的色彩序列是 BGR 
    #cv2.imshow('bimg',bimg)
    #cv2.waitKey()
    
    
    #threshold 二值化并翻转,二值化的阈值 设置为12 ,由于照片上的右侧白色部分,因为不如左侧黑色的部分明显,
    #在二值化中会被过滤掉,这里偷懒了,最好的做法是做直方图分析,获取到中间黑白的分割线,
    #然后截取黑色部分处理。所以在这里二值化的阈值大小,会影响后面分割的效果。
    #threshod infect the result!
    bimg=cv2.threshold(bimg,12,255,cv2.THRESH_BINARY_INV)[1]
    
    #调整一下图片,旋转为横向的,并且调整大小
    bimg=imutils.rotate(bimg,90)
    bimg=cv2.resize(bimg,(int(bimg.shape[1]/2),int(bimg.shape[0]/2)))
    cv2.imshow('bimg',bimg)
    cv2.waitKey()
    
    
    #contors  开始搜索轮廓
    
    #算子用的两个核
    rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
    sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(6,6))
    ##tophat 第一次遮罩
    tophat=cv2.morphologyEx(bimg,cv2.MORPH_TOPHAT,rectKernel)
    cv2.imshow('tophat',tophat)
    cv2.waitKey()
    
    ##compute 做,sobel算子边缘检测后,二次进行均值增强
    gradX=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=1)
    gradX=np.absolute(gradX)
    (minVal,maxVal)=(np.min(gradX),np.max(gradX))
    gradX=(255*((gradX-minVal)/(maxVal-minVal)))
    gradX=gradX.astype('uint8')
    
    ##2 对增强后的图像进行闭运算--二值化---二次闭预算 
    gradX=cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)
    thresh=cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
    thresh=cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel)
    
    #获得大轮廓,目的就是将白色的数字部分连在一起,方便后面的轮廓检测
    cv2.imshow('thresh',thresh)
    cv2.waitKey()
    
    #filter
    #预留,将各种噪点滤除
    ## 获取连续区域
    cnts=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    cnts=cnts[0] if imutils.is_cv2() else cnts[1]
    cnts=contours.sort_contours(cnts,method='left-to-right')[0]
    
    locs=[]
    locs2=[]
    
    #loop over the contors 循环判断连续区域的宽高比,宽度、高度是否符合预期
    for(i,c) in enumerate(cnts):
    
        (x,y,w,h)=cv2.boundingRect(c)
        ar=w/float(h)
    
    #password 4 digits       因为卡密的 数字中,四个字母一组比较多,所以设置宽高比为 2.5 --4.5 
        if ar>2.5 and ar<5.0:
            print('ar=',ar)
            print('x=',x,'y=',y,'width=',w,'height=',h)
            if(w>15 and w< 180) and (h> 15 and h<30):
                locs.append((x,y,w,h))
    # password 3 digits 3个数字的宽高比略微小点,也别漏了,当然也会带来很多噪点
        if ar>1.5 and ar<2.5:
                print('ar=',ar)
                print('x=',x,'y=',y,'width=',w,'height=',h)
                if(w>15 and w< 180) and (h> 15 and h<30):
                    locs.append((x,y,w,h))
    #number 15 digits 卡号的部分,超长,设置大点的宽高比,同时这里也有个问题就是最下面的条码宽高比是一样的,通过高度区分,这里设置h 在15-30 之间,是观察出来的。。。需要考虑图片的倾斜、小角度旋转、大小等变化
        if ar>10 or ar<20:
            if(w>100 and w< 300) and (h> 15 and h<30):
                locs2.append((x,y,w,h))
            
    print('locs=', locs)
    print('locs2=', locs2)
    
    #将检测到的轮廓在图上画出来
    if(len(locs)>0):
        output = cv2.merge([bimg] * 3)
        for (x,y,w,h) in locs:
            cv2.rectangle(output, (x - 2, y - 2), (x + w + 4, y + h + 4), (0, 255, 0), 2)
     
        if(len(locs2)>0):
     
            for (x,y,w,h) in locs2:
                cv2.rectangle(output, (x - 2, y - 2), (x + w + 4, y + h + 4), (0, 0, 255), 2)
        cv2.imshow('output',output)
        cv2.waitKey()
    

    最终的效果,左侧是进行膨胀连通之后的效果,右侧是最终进行连续路径检测之后,对数字的标注,绿色是小宽高比的标注,红色是大宽高比的标注。


    分割2.png

    目前的检测只是初步的尝试,无法应对图像的明暗、旋转、翻转、大小等多种多样的变化,仍然需要继续探索。

    相关文章

      网友评论

          本文标题:2018-01-27 充值卡OCR的尝试

          本文链接:https://www.haomeiwen.com/subject/esdoaxtx.html