ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

信用卡数字识别

2021-06-28 21:01:36  阅读:213  来源: 互联网

标签:roi 信用卡 group 数字 cardImg cv2 cnts template 识别


© Fu Xianjun. All Rights Reserved.

本次我们需要用到的知识有:阈值处理、轮廓查找、轮廓绘制、包围轮廓、开运算和闭运算、礼帽操作、边缘检测、模板匹配。

1、对模板图片进行处理,得到每个数字的模板。

import cv2
import numpy as np
def cv_show(name, img):
 cv2.imshow(name, img)
 cv2.waitKey(0)
 cv2.destroyAllWindows()
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 = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w
 (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
 key=lambda b: b[1][i], reverse=reverse))
 return cnts, boundingBoxes
# 读取模板图片
template = cv2.imread('ocr_a_reference.png')
cv_show('template', template)
# 模板图片灰度化。这里的模板图片本身就是二值化的因此没有明显区别。
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
cv_show('templage_gray', template_gray)
# 二值化,转化为数字为白色,背景为黑色的图片。
template_binary = cv2.threshold(template_gray, 127, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('template_binary', template_binary)
2、保存返回后的图片
# 根据二值化的模板图,进行轮廓检测
cnts, hierarchy = cv2.findContours(template_binary
 , cv2.RETR_EXTERNAL
 , cv2.CHAIN_APPROX_SIMPLE)
# 画出每个数字的轮廓
template_rect = cv2.drawContours(template.copy(), cnts, -1, (0,0,255), 2)
cv_show('template_rect', template_rect)
# 对十个数字根据左上角的位置进行排序,这样数字按照从小到大的顺序排列出来。
cnts = sort_contours(cnts, method="left-to-right")[0]
number = {}
# 根据排列的结果,将每个数字截取出来。将每个数字图片所对应的数字对应起来。
# 这里要注意,对像素值进行取值时,数组的行对应的是图片的y轴,列对应的图片的x轴。
for (i, cnt) in enumerate(cnts):
 (x,y,w,h) = cv2.boundingRect(cnt)
 roi = template_binary[y:y+h, x:x+w]
 roi = cv2.resize(roi, (57,88))
 
 number[i] = roi

3、去除背景

# 根据二值化的模板图,进行轮廓检测
cnts, hierarchy = cv2.findContours(template_binary
 , cv2.RETR_EXTERNAL
 , cv2.CHAIN_APPROX_SIMPLE)
# 画出每个数字的轮廓
template_rect = cv2.drawContours(template.copy(), cnts, -1, (0,0,255), 2)
cv_show('template_rect', template_rect)
# 对十个数字根据左上角的位置进行排序,这样数字按照从小到大的顺序排列出来。
cnts = sort_contours(cnts, method="left-to-right")[0]
number = {}
# 根据排列的结果,将每个数字截取出来。将每个数字图片所对应的数字对应起来。
# 这里要注意,对像素值进行取值时,数组的行对应的是图片的y轴,列对应的图片的x轴。
for (i, cnt) in enumerate(cnts):
 (x,y,w,h) = cv2.boundingRect(cnt)
 roi = template_binary[y:y+h, x:x+w]
 roi = cv2.resize(roi, (57,88))
 
 number[i] = roi

在这里插入图片描述

4、进行数字识别

# 使用sobel算子进行边缘检测,这里仅适用x方向的梯度。因为经过实验,使用x,y混合的梯度,效果并不理想。
sobelx = cv2.Sobel(cardImg_tophat, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx) (minX, maxX) = (np.min(sobelx), np.max(sobelx))
sobelx = (255 * ((sobelx - minX) / (maxX - minX)))
sobelx = sobelx.astype('uint8')
cv_show('sobelx', sobelx)
#进行闭运算,使相邻的数字连接起来,这样便于筛选。
cardImg_close = cv2.morphologyEx(sobelx, cv2.MORPH_CLOSE, rectKernel)
cv_show('cardImg_close', cardImg_close)
cardImg_binary = cv2.threshold(cardImg_close, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)[1]
cv_show('cardImg_binary', cardImg_binary)
cardImg_close = cv2.morphologyEx(cardImg_binary, cv2.MORPH_CLOSE, sqKernel)
cv_show('cardImg_close', cardImg_close)
# 轮廓检测,检测出每一个数字区块
cnts, hierarchy = cv2.findContours(cardImg_close
 , cv2.RETR_EXTERNAL
 , cv2.CHAIN_APPROX_SIMPLE)
cardImg_cnts = cv2.drawContours(cardImg.copy(), cnts, -1, (0,0,255), 2)
cv_show('cardImg_cnts', cardImg_cnts)
# 对轮廓进行筛选, 根据边框的尺寸仅保留卡号区域
locs = []
for (i, c) in enumerate(cnts):
 (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])

5、模板匹配,得到每一个数字

output = []
# 对每个4数字块进行处理
for (i, (x, y, w, h)) in enumerate(locs):
 group_output = []
 group = cardImg_gray[y-5:y + h + 5, x-5:x + w + 5]
 group = cv2.threshold(group, 0, 255, cv2.THRESH_OTSU|cv2.THRESH_BINARY)[1]
 cv_show('group', group)
 group_cnts, group_hierarchy = cv2.findContours(group
 , cv2.RETR_EXTERNAL
 , cv2.CHAIN_APPROX_SIMPLE)
 group_cnts = sort_contours(group_cnts, method="left-to-right")[0]
 # 分割每个数字
 for cnt in group_cnts:
 (nx,ny,nw,nh) = cv2.boundingRect(cnt)
 roi = group[ny:ny+nh, nx:nx+nw]
 roi = cv2.resize(roi, (57, 88))
 cv_show('roi', roi)
 score = []
 # 对每个数字进行模板匹配
 for (number_i, number_roi) in number.items():
 result = cv2.matchTemplate(roi, number_roi, cv2.TM_CCOEFF)
 score_ = cv2.minMaxLoc(result)[1]
 score.append(score_)
 group_output.append(str(np.argmax(score)))
# 绘制每个数字
 cv2.rectangle(cardImg, (x - 5, y - 5),
 (x + w + 5, y + h + 5), (0, 0, 255), 1)
 cv2.putText(cardImg, "".join(group_output), (x, y - 15),
 cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
 output.append(group_output)
cv_show('cardImg', cardImg)

标签:roi,信用卡,group,数字,cardImg,cv2,cnts,template,识别
来源: https://blog.csdn.net/weixin_56643049/article/details/118311875

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有