openCV项目实战——信用卡数字识别
代码见文末
实现效果
1. 项目背景
随着数字化支付的普及,信用卡信息的自动识别需求逐渐增加。本项目旨在实现一个基于图像处理的信用卡数字自动识别系统,能够从图片中自动提取并识别出信用卡号。该系统主要应用于金融领域,能够加速信用卡号的提取,减少人工输入错误,提高效率。
本项目通过图像处理技术,特别是模板匹配与轮廓提取的结合,完成信用卡数字的定位与识别。通过此项目,用户可以上传信用卡图像,系统能够快速、准确地识别出信用卡号和卡类型。
2. 主要步骤及其目的
步骤 1:图像预处理
-
目的:通过图像处理预处理步骤,将原图转化为适合数字识别的格式。首先读取输入图像,并将其转换为灰度图像。然后应用二值化和形态学操作增强图像中的字符和数字区域,使其适合后续的轮廓提取和数字识别。
关键操作:
- 灰度转换
- 二值化(使用OTSU算法)
- 礼帽操作突出亮区
- 使用Sobel算子提取梯度
- 闭操作填补字符间隙
步骤 2:轮廓检测与区域筛选
-
目的:通过轮廓检测来提取数字区域。首先利用
cv2.findContours()
方法找出图像中的轮廓,并根据轮廓的几何特征(长宽比、尺寸等)筛选出可能包含信用卡数字的区域。关键操作:
cv2.findContours()
提取轮廓- 根据外接矩形的长宽比和尺寸筛选出数字区域
步骤 3:数字模板创建与模板匹配
-
目的:利用手工或已有的模板图像(数字的标准样式),通过模板匹配识别数字。通过计算待匹配区域与模板之间的相似度来找出最匹配的数字。
关键操作:
- 使用
cv2.matchTemplate()
进行模板匹配 - 根据匹配分数选择最佳数字
- 使用
步骤 4:结果定位与显示
-
目的:将识别出的数字区域绘制到原图上,并显示或输出完整的信用卡号。同时,根据第一个数字判断信用卡类型。
关键操作:
- 使用
cv2.rectangle()
在图像中绘制识别框 - 使用
cv2.putText()
在图像中标注识别结果 - 输出信用卡类型与号码
- 使用
3. 相关代码片段
以下是项目中部分关键步骤的实现代码:
# 读取并预处理输入图像
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
目的:将图像转换为灰度图并进行二值化,适应后续的轮廓提取。
# 礼帽操作突出亮区
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
目的:通过礼帽操作增强图像中的高亮区域,突出字符和数字。
# 计算每个轮廓的外接矩形,并筛选合适的区域
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 and (w > 40 and w < 55) and (h > 10 and h < 20):
locs.append((x, y, w, h))
目的:根据长宽比和尺寸筛选出潜在的数字区域。
# 遍历每个数字组并进行模板匹配
for (i, (gX, gY, gW, gH)) in enumerate(locs):
group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
group_, digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
digitCnts = contours.sort_contours(digitCnts, method="left-to-right")[0]
目的:提取数字区域,进行二值化和轮廓检测,按从左到右的顺序排序数字。
# 使用模板匹配识别数字
scores = []
for (digit, digitROI) in digits.items():
result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)
(_, score, _, _) = cv2.minMaxLoc(result)
scores.append(score)
groupOutput.append(str(np.argmax(scores)))
目的:使用模板匹配方法识别数字,选择与模板最匹配的数字。
# 绘制识别结果
cv2.rectangle(image, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
cv2.putText(image, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
目的:将识别出的数字绘制到原图上,并标注结果。