Opencv项目实战:26信用卡号码识别与类型判定
- 其他
- 2025-09-02 02:33:01

项目介绍
在日常生活中,信用卡的使用越来越普遍。本项目的主要目标是通过图像处理技术自动识别信用卡号码,并根据信用卡号码的第一个数字判定信用卡的类型(如Visa、MasterCard等)。项目结合了图像预处理、轮廓检测、模板匹配等技术,实现了从输入图像中提取信用卡号码并识别其类型的功能。
项目展示Credit Card Type: MasterCard Credit Card #: 5476767898765432
项目的代码与讲解1,读取模板图像并进行预处理
首先,读取模板图像,并将其转换为灰度图像和二值图像。然后,计算模板的轮廓并进行排序。
template_img = cv2.imread(template_path) ref = cv2.cvtColor(template_img, cv2.COLOR_BGR2GRAY) ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1] refCnts, _ = cv2.findContours(ref, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) refCnts = contours.sort_contours(refCnts, method="left-to-right")[0] digits = {} for (i, c) in enumerate(refCnts): (x, y, w, h) = cv2.boundingRect(c) roi = ref[y:y + h, x:x + w] roi = cv2.resize(roi, (57, 88)) digits[i] = roi2,读取输入图像并进行预处理
读取输入图像,调整大小,通过灰度化、二值化以及形态学操作(如顶帽变换和闭操作),我们增强了图像的对比度并突出了数字部分。通过Sobel算子计算了图像的梯度,使得数字轮廓更加清晰。
image = cv2.imread(image_path) width = 300 (h, w) = image.shape[:2] r = width / float(w) dim = (width, int(h * r)) image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1) gradX = np.absolute(gradX) gradX = (255 * ((gradX - np.min(gradX)) / (np.max(gradX) - np.min(gradX)))) gradX = gradX.astype("uint8") gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)3,检测数字轮廓
在预处理后的图像中检测数字轮廓,并根据轮廓的宽高比和大小进行筛选。
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 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 and (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])4,匹配数字模板
对每个检测到的数字区域,使用模板匹配算法与模板图像中的数字进行匹配,并通过计算匹配的相似度(即相关系数)来识别每个数字。使用cv2.matchTemplate方法,我们能够准确地从检测区域中识别出每个数字,并将其按顺序拼接成完整的信用卡号码。
output = [] for (i, (gX, gY, gW, gH)) in enumerate(locs): groupOutput = [] 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] digitCnts, _ = cv2.findContours(group, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) digitCnts = contours.sort_contours(digitCnts, method="left-to-right")[0] for c in digitCnts: (x, y, w, h) = cv2.boundingRect(c) roi = group[y:y + h, x:x + w] roi = cv2.resize(roi, (57, 88)) 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) output.extend(groupOutput)5,判定信用卡类型并显示结果
根据识别到的信用卡号码的第一个数字,判定信用卡的类型,并显示结果。
print(f"Credit Card Type: {FIRST_NUMBER[output[0]]}") print("Credit Card #: {}".format("".join(output))) display_image = np.hstack([origional_img, image]) cv2.imshow("Image", display_image) cv2.waitKey(0) cv2.destroyAllWindows()完整代码如下所示:
import cv2 import numpy as np from imutils import contours image_path = r"./images/creditcard_5.png" template_path = r"reference.png" # 指定信用卡类型 FIRST_NUMBER = { "3": "American Express", "4": "Visa", "5": "MasterCard", "6": "Discover Card" } # 读取模板图像并进行预处理 template_img = cv2.imread(template_path) ref = cv2.cvtColor(template_img, cv2.COLOR_BGR2GRAY) ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1] # 计算模板轮廓并进行排序 refCnts, _ = cv2.findContours(ref, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) refCnts = contours.sort_contours(refCnts, method="left-to-right")[0] digits = {} for (i, c) in enumerate(refCnts): (x, y, w, h) = cv2.boundingRect(c) roi = ref[y:y + h, x:x + w] roi = cv2.resize(roi, (57, 88)) digits[i] = roi # 初始化卷积核 rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3)) sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 读取输入图像并进行预处理 image = cv2.imread(image_path) width = 300 (h, w) = image.shape[:2] r = width / float(w) dim = (width, int(h * r)) image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) origional_img = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 进行图像增强处理 tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1) gradX = np.absolute(gradX) gradX = (255 * ((gradX - np.min(gradX)) / (np.max(gradX) - np.min(gradX)))) gradX = gradX.astype("uint8") # 通过闭操作连接数字并进行二值化处理 gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 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 and (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]) output = [] for (i, (gX, gY, gW, gH)) in enumerate(locs): groupOutput = [] 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] digitCnts, _ = cv2.findContours(group, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) digitCnts = contours.sort_contours(digitCnts, method="left-to-right")[0] for c in digitCnts: (x, y, w, h) = cv2.boundingRect(c) roi = group[y:y + h, x:x + w] roi = cv2.resize(roi, (57, 88)) 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) output.extend(groupOutput) print(f"Credit Card Type: {FIRST_NUMBER[output[0]]}") print("Credit Card #: {}".format("".join(output))) display_image = np.hstack([origional_img, image]) # cv2.imwrite("test.png", display_image) cv2.imshow("Image", display_image) cv2.waitKey(0) cv2.destroyAllWindows() 项目总结本项目通过结合图像处理技术和模板匹配算法,成功实现了一个简单的信用卡号码识别与类型判定。
Opencv项目实战:26信用卡号码识别与类型判定由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Opencv项目实战:26信用卡号码识别与类型判定”