本文主要是介绍01、识别信用卡卡号,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import myutils
#一、绘制图像
def img_show(img_name,img):cv.imshow(img_name,img)cv.waitKey(0)cv.destroyAllWindows()#二、模板操作
#1、读取模板图像
template = cv.imread('./images/ocr_a_reference.png')
#2、将模板图像转化为灰度图像
gray = cv.cvtColor(template,cv.COLOR_BGR2GRAY)
#3、将灰度图像转化为二值图像
binary = cv.threshold(gray,10,255,cv.THRESH_BINARY_INV)[1]
#4、计算模板图像轮廓
cnts = cv.findContours(binary.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]
#5、绘制模板轮廓
cv.drawContours(template,cnts,-1,(0,0,255),3)
#6、将模板轮廓中所有轮廓从左到右排序
sort_cnts = myutils.sort_contours(cnts,method='left-to-right')[0]
#7、将每个模板与其对应的数字联系起来
digits = {}
for (i,c) in enumerate(sort_cnts): #便利每一个轮廓(x,y,w,h) = cv.boundingRect(c) #计算外界矩形并resize成合适的大小roi = binary[y:y+h, x:x+w]roi = cv.resize(roi,(57,88))digits[i] = roi #digit[i] 对应一个模板#三、信用卡图片操作
#1、初始化卷积核
rectKernel = cv.getStructuringElement(cv.MORPH_RECT,(9,3))
sqKernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5))
#2、读取信用卡图像
img = cv.imread('./images/credit_card_04.png')
#3、调整图像大小
img = myutils.resize(img,width=300)
#4、将图像转为灰度图
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
#5、礼貌操作 突出更明亮的区域
tophat = cv.morphologyEx(gray,cv.MORPH_TOPHAT,rectKernel)
#6、Sobel算子提取信用卡边缘信息
gradX = cv.Sobel(tophat,ddepth=cv.CV_32F,dx=1,dy=0,ksize=-1) #ksize=-1 <=> ksize=(3,3)
# gradX = cv.convertScaleAbs(gradX)
gradX = np.absolute(gradX)
(minval,maxval) = (np.min(gradX),np.max(gradX))
gradX = (255 * ((gradX - minval) / (maxval - minval)))
gradX = gradX.astype('uint8')
#7、闭操作,将靠近的数字连起来 将16个数字划分为4个区域
close = cv.morphologyEx(gradX,cv.MORPH_CLOSE,rectKernel)
#8、二值操作 THRESH_OTSU+thresh=0 :寻找合适的阈值,适合双峰
binary = cv.threshold(close,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)[1]
#9、闭操作 填补数字块(4个数字相连)中间的空洞
close = cv.morphologyEx(binary,cv.MORPH_CLOSE,sqKernel)
#10、计算轮廓,并在原始图片上画出轮廓
cnts = cv.findContours(close,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]
# cur_img = img.copy()
# cv.drawContours(cur_img,cnts,-1,(0,0,255),3)
#11、筛选出符合宽高比,宽高范围的所有4个数字相连的轮廓
locs = []
for (i,c) in enumerate(cnts):(x,y,w,h) = cv.boundingRect(c)w_h = w / float(h)if w_h >2.5 and w_h < 4.0: #这里要根据实际情况自己调节合适的筛选条件if (w>40 and w<55) and (h>10 and h<20):locs.append((x,y,w,h))
#12、将符合的轮廓从左到右排序
locs = sorted(locs,key=lambda x:x[0]) #四、用模板数字来匹配信用卡中的4个大轮廓
output = []
for (i,(lx,ly,lw,lh)) in enumerate(locs):groupOutput = []#1、根据坐标,提取每一组(4个数字)group = gray[ly-5:ly+lh+5,lx-5:lx+lw+5] #2、预处理 二值化group = cv.threshold(group,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)[1]#3、计算每一组的所有轮廓 并排序 digitCnts = cv.findContours(group.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]digitCnts = myutils.sort_contours(digitCnts,method='left-to-right')[0]#计算每一组中的每一个值for c in digitCnts:#1、显示每个轮廓的每个数字(x,y,w,h) = cv.boundingRect(c)roi = group[y:y+h,x:x+w]roi = cv.resize(roi,(57,88))#2、统计数字roi与模板中每个数字匹配后的得分scores = []for (digit,digitLoc) in digits.items():#模板匹配res = cv.matchTemplate(roi,digitLoc,cv.TM_CCOEFF_NORMED)score = cv.minMaxLoc(res)[1]scores.append(score)#将数字roi在模板中匹配到的坐标(值)存在groupOutput中groupOutput.append(str(np.argmax(scores)))#把每个小方块(四个数字)显示出来cv.rectangle(img,(lx-5,ly-5),(lx+lw+5,ly+lh+5),(0,0,255),2)output.extend(groupOutput)cv.putText(img,"".join(groupOutput),(lx,ly-15),cv.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2) #五、显示
print("Credit Card:{}".format("".join(output)))
img_show('img',img)
myutils.py
import cv2
# 对轮廓进行排序
def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1# 计算外接矩形 boundingBoxes是一个元组boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w# sorted排序(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxes # 轮廓和boundingBoxess
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return imageif width is None:r = height / float(h)dim = (int(w * r), height)else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation=inter)return resized
这篇关于01、识别信用卡卡号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!