from imutils import contours import numpy as np import argparse import cv2 as cv import myutils def cv_show(name,img): cv.imshow(name,img) cv.waitKey(0) cv.destroyAllWindows() # 先处理template tempalte_img = cv.imread("E:/opencv/picture/ocr_a_reference.png") tempalte_gray = cv.cvtColor(tempalte_img, cv.COLOR_BGR2GRAY) tempalte_thres = cv.threshold(tempalte_gray, 0, 255, cv.THRESH_OTSU | cv.THRESH_BINARY_INV)[1] temp_a, tempalte_contours, temp_b = cv.findContours(tempalte_thres.copy (), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) cv.drawContours(tempalte_img, tempalte_contours, -1, (0, 255, 0), 2) tempalte_contours = contours.sort_contours(tempalte_contours, method="left-to-right")[0] digits = {} # 构建一个字典 for (i, c) in enumerate(tempalte_contours): (x, y, w, h) = cv.boundingRect(c) tempalte_roi = tempalte_thres[y:y + h, x:x + w] #之前一直检测不出正确答案,原因是这里的roi应该是tempalte_thres一部分 #而不是template_gray的一部分! tempalte_roi = cv.resize(tempalte_roi, (57, 88)) digits[i] = tempalte_roi cv_show('template_single',tempalte_roi) #cv_show('template_single',tempalte_roi) #对银行卡进行处理,之所以要做成数字长条,是想通过长条的尺寸比例大小来将自己想要的数字给抠出来。 rectkernel = cv.getStructuringElement(cv.MORPH_RECT,(9,3)) squrkernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5)) image = cv.imread("E:/opencv/picture/credit_card_02.png") image = myutils.resize(image, width=300) image_gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) image_tophat= cv.morphologyEx(image_gray,cv.MORPH_TOPHAT,rectkernel) image_close = cv.morphologyEx(image_tophat,cv.MORPH_CLOSE,rectkernel) cv.imshow("image_tophat",image_tophat) cv.imshow('image_close',image_close) image_thres= cv.threshold(image_close,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)[1] image_contours= cv.findContours(image_thres.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[1] locs = [] for(n,con) in enumerate(image_contours): (gx,gy,gw,gh)= cv.boundingRect(con) ar = gw/float (gh) if ar > 2.5 and ar < 4.0: if (gw > 40 and gw < 55) and (gh > 10 and gh < 20): # 符合的留下来 locs.append((gx, gy, gw, gh)) #sorted和contours.sort_contours的区别:第二个是针对轮廓的排序 # 将符合的轮廓从左到右排序 sorted针对的是一个list 而sort_countours函数是针对多个轮廓数组 locs = sorted(locs, key=lambda x:x[0]) output = [] for(i,(x,y,w,h))in enumerate(locs): groupOutput = [] group = image_gray[y-5:y+h+5,x-5:x+w+5] group = cv.threshold(group,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)[1] digcnts = cv.findContours(group.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[1] digcnts = contours.sort_contours(digcnts,method="left-to-right")[0] for c in digcnts: (gx,gy,gw,gh) = cv.boundingRect(c) roi = group[gy:gy+gh,gx:gx+gw]#注意这里是对group进行寻找轮廓的,所以得到的轮廓向量的外接矩形的坐标是针对 #group的 roi = cv.resize(roi, (57, 88)) cv_show('roi',roi) # 计算匹配得分 scores = [] # 在模板中计算每一个得分 #先从第一个group的第一个roi开始作为第一个检测对象,遍历模板字典里各个模板,分别得到对应的匹配结果score #我们取score值最大的对应的字符串作为模板匹配后识别到的第一个结果,并加入到groupOutput里去。 #然后再将第一个group的第二个roi作为第二个检测对象,遍历模板字典里各个模板,分别得到对应的匹配结果score #我们取score值最大的对应的字符串作为模板匹配后识别到的第二个结果,并加入到groupOutput里去。 #以此循环,一共有4*4个roi,所以这个过程要循环16次。最终识别到的结果存储到了groupOutput里去 for (digit, digitROI) in digits.items(): # 模板匹配 result = cv.matchTemplate(roi, digitROI, cv.TM_CCOEFF_NORMED) (_, score, _, _) = cv.minMaxLoc(result) scores.append(score) # 得到最合适的数字 groupOutput.append(str(np.argmax(scores))) cv.rectangle(image, (x - 5, y - 5), (x + w + 5, y + h + 5), (0, 0, 255), 1) cv.putText(image, "".join(groupOutput), (x, y - 15), cv.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2) # 得到结果 output.extend(groupOutput) # 打印结果 cv.imshow("Image", image) cv.waitKey(0) 在本示例中,我们探讨了如何利用OpenCV库进行图像处理,特别是针对信用卡上的数字进行识别。这个案例主要涉及以下几个关键知识点: 1. **图像预处理**:我们加载了一个参考模板图像(`ocr_a_reference.png`),并对其进行灰度化、二值化处理。之后,使用轮廓检测找到数字模板的轮廓,并根据轮廓排序,以便后续的匹配过程。 2. **模板匹配**:创建了一个名为`digits`的字典,存储了经过调整大小的每个数字模板。模板匹配是识别过程中重要的一环,它利用`cv.matchTemplate`函数,对银行卡图像上找到的每个数字候选区域与模板进行比较,以找到最佳匹配。 3. **银行卡图像处理**:读取信用卡图像(`credit_card_02.png`),同样进行灰度化处理,接着应用顶帽变换(`cv.morphologyEx` with `cv.MORPH_TOPHAT`)和闭运算(`cv.MORPH_CLOSE`)来增强数字边缘。然后进行二值化处理,找到轮廓,并筛选出符合条件的数字长条形区域。 4. **轮廓排序**:使用`contours.sort_contours`函数按特定顺序排列轮廓,这里是按从左到右的顺序,确保数字识别的顺序正确。 5. **局部区域处理**:对每个筛选出的数字区域,提取其内部的轮廓,再次进行二值化处理,然后对这些小的区域进行模板匹配,找出最匹配的数字模板。 6. **匹配得分与选择**:对于每个数字候选区域,计算所有模板的匹配得分,使用`cv.minMaxLoc`获取最高得分,并将对应模板的数字添加到结果列表中。 7. **输出与可视化**:识别出的数字组合成完整的信用卡号,并在原始图像上绘制矩形框和文本,最后显示处理后的图像。 此外,还提到了Python中的一些编程技巧: - `contours.sort_contours`函数用于根据特定规则(如轮廓的位置)对轮廓进行排序。 - 使用`zip`和`sorted`函数配合`lambda`表达式,可以方便地对轮廓和它们的边界框进行排序。 - `boundingRect`函数用于计算轮廓的最小外接矩形。 整个流程展示了如何利用OpenCV和Python实现复杂图像处理任务,包括预处理、特征提取、模板匹配和后处理,以及对图像数据的有效操作。这些技能在实际的OCR(光学字符识别)系统和其他图像分析应用中是非常重要的。


剩余12页未读,继续阅读
- 粉丝: 2
我的内容管理
展开
我的资源
快来上传第一个资源
我的收益 登录查看自己的收益
我的积分
登录查看自己的积分
我的C币
登录后查看C币余额
我的收藏
我的下载
下载帮助
前往需求广场,查看用户热搜最新资源
- robomaker-jvm-1.4.2-sources.jar
- reconf-client-1.6.9-sources.jar
- inspectorscan-jvm-1.4.77-sources.jar
- jeap-spring-boot-db-migration-starter-it-17.28.0.jar
- iottwinmaker-jvm-1.3.71-javadoc.jar
- nunaliit2-auth-common-0.1.8.1-sources.jar
- easyconfiguration-feature-text-4.0.6-sources.jar
- http-client-engine-okhttp-1.0.16-javadoc.jar
- panorama-jvm-1.5.1-javadoc.jar
- qapps-jvm-1.4.79-sources.jar
- transfer-jvm-1.1.9.jar
- qldbsession-jvm-0.17.9-beta-sources.jar
- gen_2.11-dj.jar
- annotation-1.5.0.jar
- greengrassv2-jvm-1.2.31.jar
- nimble-jvm-1.2.56-javadoc.jar


信息提交成功