案例3-使用python实现基于opencv的银行卡号识别

该案例主要巩固所学opencv基础知识,有轮廓检测,形态学知识以及模板匹配。以及python基础知识和对矩阵的运算
该案例分为两部分,第一部分使用鼠标选取数字部分,并保存。


```python
import cv2
import numpy as np
cv2.namedWindow('cardNum')
card = cv2.imread('./img/images/credit_card_01.png')
model = cv2.imread('./img/images/ocr_a_reference.png')
card2 = card.copy()
#鼠标截取范围
StartX = 0
StartY = 0
w = 0
h = 0
flag_c = 0
flag_rect = False

def mouse(event,x,y,flags,userdata):
    global StartX, StartY,w,h,flag_rect,card
    if event == cv2.EVENT_LBUTTONDOWN:
        flag_rect = True
        StartX = x
        StartY = y
        #print("left down")
    elif event == cv2.EVENT_LBUTTONUP:
        flag_rect = False
        cv2.rectangle(card,(StartX,StartY), (x,y), (0,255,0), 2)
        w = abs(StartX-x)
        h = abs(StartY-y) 
        print(StartX,StartY,w,h)
    elif event == cv2.EVENT_MOUSEMOVE:
        if flag_rect == True:
            card = card2.copy()
            cv2.rectangle(card,(StartX,StartY),(x,y),(0,255,0),2)
            #print("move")





cv2.setMouseCallback('cardNum',mouse)




#ROI = card[rect[0]:rect[0]+rect[2],rect[1]:rect[1]+rect[3]]
print(StartX,StartY,w,h)

while True:
    cv2.imshow('cardNum',card)
    if flag_c ==1:
        ROI = card[StartY:StartY+h-1,StartX:StartX+w-1]
        cv2.imwrite('./img/images/roi.png',ROI)

        #cv2.imshow('ROI2',card_Gray4)
        #cv2.imshow('model',model)
#    cv2.imshow('ROI',ROI)
    k =cv2.waitKey(100)
    if k== 27:
        break
    if k == ord('o'):
        flag_c = 1
cv2.destroyAllWindows()

在这里插入图片描述


第二部分为图像处理和识别部分
import cv2

import numpy as np

ka = cv2.imread('./img/images/credit_card_02.png')
ka2 = ka.copy()
#card = ka2[189:233,42:541]
card = cv2.imread('./img/images/roi2.png')
model = cv2.imread('./img/images/ocr_a_reference.png')
#更改大小-和template大小相似
Gray2 = cv2.resize(card,(2*card.shape[1],2*card.shape[0]))
model = cv2.resize(model,(int(0.7*model.shape[1]),int(0.7*model.shape[0])))




#数字排序
def sequence(image):
    contours, _ = cv2.findContours(image,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    #cv2.drawContours(Gray2,contours,-1,(0,0,255),2)
    n = len(contours)
    #创建n*4的矩阵
    RectBoxes0 = np.ones((n,4),dtype = int)
    for i in range(n):
        RectBoxes0[i] = cv2.boundingRect(contours[i])
    RectBoxes = np.ones((n,4),dtype = int)
    for i in range(n):
        ftemp = 0
        for j in range(n):
            if RectBoxes0[i][0] > RectBoxes0[j][0]:
                ftemp = ftemp+1
            RectBoxes[ftemp] = RectBoxes0[i]
    ImgBoxs = [[] for i in range(n)]
    for i in range(n):
        x,y,w,h = RectBoxes[i]
        ROI = image[y:y+h,x:x+w]
        ROI = cv2.resize(ROI,(50,80))
        _,ROI = cv2.threshold(ROI,200,255,cv2.THRESH_BINARY)
        ImgBoxs[i] = ROI
    return RectBoxes,ImgBoxs




#灰度化
card_Gray = cv2.cvtColor(Gray2,cv2.COLOR_BGR2GRAY) 
model_Gray = cv2.cvtColor(model,cv2.COLOR_BGR2GRAY) 
#自适应二值化  高斯确定阈值法 21:自适应确定阈值的邻域大小   3:平均值减去的数 
thresh = cv2.adaptiveThreshold(card_Gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,21,3)
_,thresh_model = cv2.threshold(model_Gray,200,255,cv2.THRESH_BINARY)
thresh_model = cv2.bitwise_not(thresh_model)
#逻辑非运算-黑白转换
thresh = cv2.bitwise_not(thresh)
#发现轮廓
contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#如果轮廓面积小于60变为黑色
for i in range(len(contours)):
    if cv2.contourArea(contours[i]) < 60:
        threshs = cv2.drawContours(thresh,contours,i,(0,0,0),-1)
#黑帽运算--
kernel = np.ones((15,15),dtype=np.uint8)
blackhat = cv2.morphologyEx(threshs,cv2.MORPH_BLACKHAT,kernel)
#腐蚀运算
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
erodes = cv2.erode(blackhat,kernel2,iterations=1)
#closes = cv2.morphologyEx(erodes,cv2.MORPH_CLOSE,kernel2,iterations=3)
contours,_ = cv2.findContours(erodes,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#根据图像面积和长宽比进行选取
for i in range(len(contours)):
    x,y,w,h = cv2.boundingRect(contours[i])
    aspect_ratio = float(w)/h
    A = float(w)*h
    if A<700 or A>4000:
        erodes = cv2.drawContours(erodes,contours,i,(0,0,0),-1)
    elif aspect_ratio>7.0 or aspect_ratio <0.5:
        erodes = cv2.drawContours(erodes,contours,i,(0,0,0),-1)
#膨胀后,model和value数字宽度合适
dilation = cv2.dilate(erodes,kernel2,iterations=1)
rectBox,ROIbox = sequence(dilation)
ModelBox,ModelROIbox = sequence(thresh_model)
#模板匹配

score = np.zeros(len(ModelROIbox),dtype=int)
for i in range(len(ROIbox)):
    for j in range(len(ModelROIbox)):
        score[j] = cv2.matchTemplate(ROIbox[i],ModelROIbox[j],cv2.TM_SQDIFF)
    min_val,max_val,min_indx,max_indx = cv2.minMaxLoc(score)
    string=str(min_indx[1])
    cv2.putText(ka,string,(90+i*25,195),2,1,(0,0,255))


#print(rect)
cv2.imshow('dilation',ka)
#cv2.imshow('r',r)
cv2.waitKey()

![在这里插入图片描述](https://img-blog.csdnimg.cn/249bfbcc1fdc44e9a647d71ef898c848.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA54Ok57qi6Jav6YWN6bG_6bG85Lid,size_14,color_FFFFFF,t_70,g_se,x_16#pic_center)

猜你喜欢

转载自blog.csdn.net/qq_33392383/article/details/122831425