计算机视觉opencv之图片旋转模版匹配银行卡号的识别

计算机视觉opencv之图片旋转模版匹配银行卡号的识别 一、图片旋转图片旋转 import cv2 import numpy as np #第一种方法用numpy实现 img cv2.imread() rotated_img1np.rot90(img,k-1)#旋转90度-1是顺时针旋转1为逆时针旋转 rotated_img2np.rot90(img,k1) cv2.imshow(yuantu,img) cv2.imshow(image1shun,rotated_img1) cv2.imshow(image2ni,rotated_img2) cv2.waitKey(0) cv2.destroyAllWindows() #第二种用opencv rotated_imgcv2.rotate(img,cv2.ROTATE_90_CLOCKWISE)#顺时针90度 rotated_img2cv2.rotate(img,cv2.ROTATE_90_COUNTERCLOCKWISE)#逆时针90度 rotated_img3cv2.rotate(img,cv2.ROTATE_180)#旋转180度 cv2.imshow(shun90,rotated_img) cv2.imshow(ni90,rotated_img2) cv2.imshow(180,rotated_img3) cv2.waitKey(0)二、模版匹配模版与多个对象匹配 import cv2 import numpy as np img_rgbcv2.imread() img_graycv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY) templatecv2.imread() h,wtemplate.shape[:2] #使用模版匹配方法cv2.matchTemplate,进行模板匹配 rescv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) #设定匹配阈值 threshold0.9 #获取匹配结果中所有符合阈值的点坐标 locnp.where(res threshold) #print(loc) #遍历所有匹配点 for pt in zip(*loc[::-1]): #在原图上绘制匹配区域的矩形框 cv2.rectangle(img_rgb,(pt[0]w,pt[1]h),(0,0,255),1) cv2.imshow(img,img_rgb) cv2.waitKey(0)三、框选图片目标利用上面图片旋转和模板匹配template需要进行框选的图片import cv2 import numpy as np def pipei(img_rgb,template): img_graycv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY) h,wtemplate.shape[:2] rescv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) threshold0.9 locnp.where(res threshold) for pt in zip(*loc[::-1]): cv2.rectangle(img_rgb,pt,(pt[0]w,pt[1]h),(0,0,255),1) return img_rgb img_rgbcv2.imread(yuantu1.jpg) templatecv2.imread(jiantou.jpg,0) template2np.rot90(template,k-1) template3np.rot90(template,k1) img_rgbpipei(img_rgb,template) img_rgbpipei(img_rgb,template2) img_rgbpipei(img_rgb,template3) cv2.imshow(img_rgb,img_rgb) cv2.waitKey(0)结果四、银行卡号识别1.导入模块import numpy as np import argparse import cv2 import myutils2.设置参数在上一篇视觉博客中提到过的传入参数的方法这里我们设置两个参数一个是传入的照片一个是识别模版传入的照片识别模板为了方便这里我们设定义一个函数用来展示图片的#设置参数 apargparse.ArgumentParser() ap.add_argument(-i,--image,requiredTrue,helppath to input image) ap.add_argument(-t,--template,requiredTrue,helppath to template OCA-A image) argsvars(ap.parse_args()) def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0)3.轮廓获取对模板中每歌数字轮廓进行获取检测到轮廓ref输入图像必须是二值图cv2.RETR_EXTERNAL轮廓检索模式只检测最外层轮廓cv2.CHAIN_APPROX_SIMPLE 轮廓近似方法压缩水平/垂直/对角线方向点。------------母版图像中数字的定位处理------------- imgcv2.imread(args[template])#读取模板图 cv_show(img,img) refcv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转为灰度图 cv_show(ref,ref) refcv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]#二值化并反色达到黑底白字效果 cv_show(ref,ref) #轮廓检测与排序 _,refCnts,hierarchycv2.findContours(ref,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#检测轮廓 cv2.drawContours(img,refCnts,-1,(0,0,255),3)#绘制轮廓 cv_show(refCnts,img) refCntsmyutils.sort_contours(refCnts,methodleft-to-right)[0]#从左到右排列 digits{}#字典存储数字模板 for (i,c) in enumerate(refCnts): (x,y,w,h)cv2.boundingRect(c)#获取轮廓外接矩形 roiref[y:yh,x:xw]#裁剪出单个数字 roicv2.resize(roi,(57,88))#统一尺寸为57x88像素 cv_show(ro ,roi) digits[i]roi#按照顺序存入字典0——0,1——1…… print(digits)#打印字典:{0:数字0的矩阵1::数字1的矩阵……9:数字9的矩阵将0-9像素矩阵对应到具体的数字构造为字典存放在digists当中4.银行卡图像处理这里使用顶帽忽略掉卡上一些小细节凸显数字------------------信用卡的图像处理----------- #读取输入的图像预处理 imagecv2.imread(rcard1.png) cv_show(image,image) imagemyutils.resize(image,width300)#设置图像大小 graycv2.cvtColor(image,cv2.COLOR_BGR2GRAY) cv_show(gray,gray) #顶帽处理突出图像中的亮细节清楚背景图因为背景图颜色变化小不被腐蚀掉 rectKernelcv2.getStructuringElement(cv2.MORPH_RECT,(9,3)) sqKernelcv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) tophatcv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel) # opencv2.morphologyEx(gray,cv2.MORPH_OPEN,rectKernel) # cv_show(open,open) cv_show(tophat,tophat)读取输入的图像也就是card1.png灰度图处理处理掉卡背景的杂质5.找数字边框这块是主要核心如果我们处理图片不当就会影响我们的输出结果-------------找到数字边框-------------------------- #通过闭操作先膨胀后腐蚀将数字连在一起 closexcv2.morphologyEx(tophat,cv2.MORPH_CLOSE,rectKernel) cv_show(close1,closex) #Tjresh_otsu会自动寻找合适的阈值适合双峰需要把阈值参数设置为0 threshcv2.threshold(closex,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] cv_show(thresh,thresh) #闭操作 threshcv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel) cv_show(close2,thresh) #计算轮廓 _,cnts,hcv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cnts_imgimage.copy() cv2.drawContours(cnts_img,cnts,-1,(0,0,255),3) cv_show(cnts_img,cnts_img) #遍历轮廓找到数字部分像素区域 locs[] for c in cnts: (x,y,w,h)cv2.boundingRect(c) arw / float(h) #选择合适的区域根据实际任务 if 2.5 ar 4.0: if (40w55) and (10h20): locs.append((x,y,w,h)) #将符合的轮廓从左到右排列 locssorted(locs,keylambda x: x[0]) print(locs)这里筛选出我们需要的轮廓长宽等是根据实际情况估计的可以多次修改筛选到对应的卡号轮廓这里我们得到四个边框是因为银行卡号是四块数字分开的6.遍历轮廓中各个数字三个循环第一个循环是遍历找到的每个数字组第二个循环遍历组内的每个数字第三个循环是与0-9模板逐一匹配output[] # 遍历每一个轮廓中的数字 for (gx,gy,gw,gh) in locs: groupoutput[] groupgray[gy-5:gygh5,gx-5:gxgw5]#扩展边界避免边缘切割 cv_show(group,group) #预处理 groupcv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]#自动二值化 cv_show(group,group) #计算每一组的轮廓 group_,digitscnts,hierarchycv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#在二值化的每个group中找每个数字的轮廓 digitscntsmyutils.sort_contours(digitscnts,methodleft-to-right)[0]#排序 #计算每一组中的每一个数值 for c in digitscnts: #找到当前数值的轮廓resize成合适的大小 (x,y,w,h)cv2.boundingRect(c) roigroup[y:yh,x:xw]#裁剪出单个数字 roicv2.resize(roi,(57,88))#统一到模板尺寸 cv_show(roi,roi) -----使用模版匹配计算匹配的得分 scores[] #在模版中计算每一个得分 for (digit,digitroi) in digits.items(): #模版匹配 resultcv2.matchTemplate(roi,digitroi,cv2.TM_CCORR) (_,score,_,_)cv2.minMaxLoc(result) scores.append(score) #得到最合适的数字 groupoutput.append(str(np.argmax(scores))) #画图 cv2.rectangle(image,(gx-5,gy-5),(gxgw5,gygh5),(0,0,255),1) # cv2.putText()是opencv库中的一个函数用于在图像上添加文本 cv2.putText(image,.join(groupoutput),(gx,gy-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2) output.extend(groupoutput)#得到结果将一个列表的元素添加到另一个列表的末尾7.打印结果#打印结果 print(credit card type:{}.format(FIRST_NUMBER[output[0]])) print(credit card #:{}.format(.join(output))) cv2.imshow(image,image) cv2.waitKey(0)