首页 > 编程知识 正文

通过卡号判断是不是信用卡,怎么看卡号是不是信用卡

时间:2023-05-03 12:20:35 阅读:252330 作者:2725

信用卡卡号识别 大致思想:

​ 1)先为信用卡上的数字设计一个模板图像(不同信用卡上的数字会有差异,按实际情况进行处 理),以便于之后进行模板匹配

​ 2)对模板图像进行外轮廓检测并得到当前外轮廓的外接矩形

​ 3)对信用卡图像进行外轮廓检测,如下图信用卡的卡号是分为了四组,每组四个数字,故可以通过 图像的闭操作等相关操作对该信用卡的卡号进行分组处理(四大组)

​ 4)得到信用卡的外接矩形,并根据外接矩形的宽高比例的差异排除其它无用的轮廓信息

​ 5)使用for循环,将各组中的四个数字再次进行如上的预处理操作;特别注意要将模板中的数字框 外接矩形与信用卡中数字框的外接矩形resize成同样大小

​ 6)使用for循环依次进行模板匹配

模板图像:

​ numbers.png

信用卡图像:

​ creditcard.png

1.导入需要的工具包 import cv2import numpy as npimport myutils #另一个py文件 2.设置一个展示函数 def cv_show(name,img):cv2.imshow(name,img)cv2.waitKey(0)cv2.destroyAllWindows() 3.读入模板图像并进行一系列预处理 img=cv2.imread('numbers.png')cv_show('img',img)#转为灰度图ref=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)cv_show('ref',ref)#转为二值图(进行轮廓检测时,只能用二值图)ref=cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]cv_show('ref',ref)#计算轮廓refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cv2.drawContours(img,refCnts,-1,(0,0,255),3)cv_show('img',img)print(np.array(refCnts).shape)#对轮廓进行排序refCnts=myutils.sort_contours(refCnts,'left-to-right')[0]digits={}for (i,c) in enumerate(refCnts): #计算外接矩形并resize成合适大小 (x,y,w,h)=cv2.boundingRect(c) roi=ref[y:y+h,x:x+w] roi=cv2.resize(roi,(57,88)) digits[i]=roi 4.读入信用卡图像并进行一系列预处理 #初始卷积核,默认的卷积核大小为3*3rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))#读取输入图像,预处理image1=cv2.imread('creditcard.png')cv_show('image1',image1)image1=myutils.resize(image1,width=300)gray=cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)cv_show('gray',gray)#礼帽操作,突出更明亮的区域tophat=cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)cv_show('tophat',tophat)#将信用卡上的边缘提取出来gradX=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)#ksize=-1相当于3*3的卷积核gradX=np.absolute(gradX)#绝对值处理(minVal,maxVal)=(np.min(gradX),np.max(gradX))gradX=(255*((gradX-minVal)/(maxVal-gradX)))gradX=gradX.astype('uint8')print(np.array(gradX).shape)cv_show('gradX',gradX)#将靠近的数字连在一起,从而可以划分出四个数字区域#通过闭操作(先膨胀,后腐蚀)将数字连在一起gradX=cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)cv_show('gradX',gradX)#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0thresh=cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]cv_show('thresh',thresh)#再来一个闭操作thresh=cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel)cv_show('thresh',thresh)#计算轮廓,并将轮廓画在原始图片上threshCnts,hierarchy=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts=threshCntscur_img=image1.copy()cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)cv_show('img',cur_img) 5.保留卡号信息的轮廓,排除无关轮廓 #遍历所有的轮廓,按照宽高比将需要的四个数字的轮廓提取出来locs=[]for (i,c) in enumerate(threshCnts):#cv2.boundingRect()返回的是一个元组(x,y,w,h) (x,y,w,h)=cv2.boundingRect(c) ar=w/float(h) # 选择合适的区域,根据实际任务来,这里的基本都是四个字一组 if ar > 2.5 and ar < 4.0: if (w > 40 and w < 55) and (h > 10 and h < 20): # 符合的留下来 locs.append((x, y, w, h))# 将符合的轮廓从左到右排序locs = sorted(locs, key=lambda x: x[0]) 6.进行模板匹配

上述操作完成后,有用的卡号轮廓信息已经单独保存下来。将信用卡的卡号信息分为四个大组,每个大组中又分为四个小组,使用嵌套的for循环对每个数字进行模板匹配。当然,在模板匹配前还需要对每一组进行预处理操作,如二值化处理、找出各个数字的轮廓、绘制外接矩形等,步骤与上述找出信用卡上的轮廓相同。

output=[]#用于存放各个数字的数组for (i,(x,y,w,h)) in enumerate(locs): groupOutput=[]#用于存放当前组中的数据,每进行一组预处理操作之前先清空该数组 #根据坐标提取每一组 group=gray[y-5:y+h+5,x-5:x+w+5] cv_show('group',group) #上述已经进行了灰度处理,下面进行二值化处理等操作(与之前类似) group=cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] cv_show('group',group) #计算每一组中各个数字的轮廓 digitsCnts,hierarchy=cv2.findContours(group,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) digitCnts=myutils.sort_contours(digitCnts,method='left-to right')[0] for c in digitCnts: (x1,y1,w1,h1)=cv2.boundingRect(c) roi=group[y1:y1+h1,x1:x1+w1] roi=cv2.resize(roi,(57,88)) cv_show('roi',roi) #计算匹配得分 scores=[] for (digitCnts,digitROI) in digits.items(): result=cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF) (_,score,_,_)=cv2.minMaxLoc(result) scores.append(score) #得到最合适的数字,将分值最大的数字添加至groupOutput数组中 groupOutput.append(str(np.argmax(scores)))#为信用卡上的四个组绘制外接矩形 cv2.rectangle(image,(x-5,y-5),(x+w+5,y+h+5),(0,0,255),1) #将信用卡的卡号写在卡号处的上方 cv2.putText(image,''.join(groupOutput),(x,y-15),cv2.FONT_HERSHEY, 0.65,(0,0,255),2)#将每组中的数字添加到整个卡号数字组中 output.extend(groupOutput) 7.myutils.py文件 import cv2#用于排序def sort_contours(cnts,method='left-to-right'): reverse=False i=0 if method=='right-to-left' or method=='bottom-to-top': reverse=True if method=='top-to-bottom' or method=='bottom-to-top': i=1 #用一个最小的矩形,把找到的形状包起来;boundingBoxes是一个包含(x,y,h,w)的元组 boundingBoxes=[cv2.boundingRect(c) for c in cnts] #将各轮廓从左至右排序 (cnts,boundingBoxes)=zip(*sorted(zip(cnts,boundingBoxes),key=lambda b:b[1] [i],reverse=reverse)) return cnts,boundingBoxes#用于调整图片大小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 image if 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 8.展示最终的结果 print('credit card type is:{}'.format(FIRST_NUMBER[output[0]]))print('credit card #:{}'.format(''.join(output)))cv_show('image',image)

上述内容是通过观看相关课程以及一些博主的内容进行的总结,这都是对图像基本操作的简单运用,但由于其中涉及到的知识还需要额外拓展,所以大家可以根据自己的情况进行学习

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。