信用卡数字识别项目 - 代码解析与实现

本文介绍了使用OpenCV进行信用卡数字自动识别的项目过程,包括图像预处理、数字与信用卡号码的分割、模板匹配等技术。项目经验强调了图像预处理、形态学处理的重要性以及模板匹配的局限性,同时建议使用大规模数据集提升准确性。
摘要由CSDN通过智能技术生成

1. 项目思路流程

本项目旨在实现对信用卡上的数字进行自动识别,并输出信用卡类型和信用卡号码。项目的主要步骤如下:

  1. 导入所需的库:导入OpenCV、imutils、matplotlib和numpy等库,以便进行图像处理和显示。

  2. 加载图像:读取信用卡和数字图像,并将其转换为灰度图像,以便后续处理。

  3. 数字图像预处理:对数字图像进行阈值化处理,将数字区域分离出来,并通过轮廓查找找到每个数字的位置。

  4. 数字图像分割:对数字图像进行排序和处理,将每个数字提取出来,并保存在一个字典中。

  5. 信用卡图像预处理:对信用卡图像进行形态学处理,提取出信用卡号码的区域。

  6. 信用卡号码分割:对信用卡号码区域进行处理,分割出每个数字,并通过模板匹配方法与保存的数字模板进行对比,得到最终的信用卡号码。

  7. 输出结果:输出信用卡类型和信用卡号码。

 2. 核心代码实现

以下是项目的核心代码实现,展示了数字图像预处理、信用卡图像预处理、数字识别等关键步骤的代码:

2.1 数字图像的预处理:

# 对数字图像进行阈值化处理,并查找数字轮廓
    plt.figure('numbers阈值化及轮廓查找')
    _,gray_bin = cv2.threshold(num_gray, 10, 255, cv2.THRESH_BINARY_INV)
    plt.subplot(1,2,1)
    plt.imshow(gray_bin, cmap='gray')
    num_contours,_ = cv2.findContours(gray_bin.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(number, num_contours, -1, (0, 255, 0), 3)
    plt.subplot(1,2,2)
    plt.imshow(number,cmap='gray')
# 对数字轮廓进行排序和处理,将每个数字放入digits字典中
    num_contours = contours.sort_contours(num_contours,method='left-to-right')[0]
    digits = {}
    for (i,c) in enumerate(num_contours):
        (x,y,w,h) = cv2.boundingRect(c)
        roi = gray_bin[y:y+h,x:x+w]
        roi = cv2.resize(roi,(57,88))
        digits[i] = roi

2.2 信用卡图像预处理:

# 形态学处理和边缘查找
    plt.figure('card形态学处理及边缘查找')
    #算子初始化
    rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
    sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
    #礼帽运算
    tophat = cv2.morphologyEx(card_gray,cv2.MORPH_TOPHAT,rectKernel)
    plt.subplot(2,3,1)
    plt.imshow(tophat,cmap='gray')
    #梯度运算
    gradX = np.abs(cv2.Sobel(tophat,cv2.CV_32F,1,0,ksize=3))
    #归一化处理
    (minVal,maxVal) = (np.min(gradX),np.max(gradX))
    gradX = (255*((gradX-minVal)/(maxVal-gradX))).astype(np.uint8)
    plt.subplot(2,3,2)
    plt.imshow(gradX,cmap='gray')
    #闭运算
    gradX = cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)
    plt.subplot(2,3,3)
    plt.imshow(gradX,cmap='gray')
    #阈值化
    gradX_bin = cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
    plt.subplot(2,3,4)
    plt.imshow(gradX_bin,cmap='gray')
    gradX_bin = cv2.morphologyEx(gradX_bin,cv2.MORPH_CLOSE,sqKernel)
    plt.subplot(2,3,5)
    plt.imshow(gradX_bin,cmap='gray')
    # 卡片数字轮廓查找
    card_contours,_ = cv2.findContours(gradX_bin.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    card_copy = card.copy()
    cv2.drawContours(card_copy,card_contours,-1,(0,255,0),3)
    plt.subplot(2,3,6)
    plt.imshow(card_copy[:,:,::-1])

2.3 数字识别:

# 数字识别
    plt.figure('结果')
    locs = []
    for (i,c) in enumerate(card_contours):
        (x,y,w,h) = cv2.boundingRect(c)
        print('第',i,'组数字',(x,y,w,h),'\n')
        ar = w/float(h)
        if ar>3 and ar<4.0:
            if(w>50 and w<60) and (h>10 and h<20):
                locs.append((x,y,w,h))
    locs = sorted(locs,key=lambda x:x[0])
    print(locs)
    output = []
    k=1
    for (i,(gX,gY,gW,gH)) in enumerate(locs):
        groupOutput = []
        group = card_gray[gY-5:gY+gH+5,gX-5:gX+gW+5]
        group = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
        plt.subplot(2,2,k)
        plt.imshow(group,cmap='gray')
        k+=1
        group_contours,_ = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        group_contours = contours.sort_contours(group_contours,method='left-to-right')[0]
        for c in group_contours:
            (x,y,w,h) = cv2.boundingRect(c)
            roi = group[y:y+h,x:x+w]
            roi = cv2.resize(roi,(57,88))
            scores = []
            for (digit,digit_roi) in digits.items():
                result = cv2.matchTemplate(roi,digit_roi,cv2.TM_CCOEFF)
                (_,score,_,_) = cv2.minMaxLoc(result)
                scores.append(score)
            groupOutput.append(str(np.argmax(scores)))
        cv2.rectangle(card,(gX-5,gY-5),(gX+gW+5,gY+gH+5),(0,255,0),3)
        cv2.putText(card,"".join(groupOutput),(gX,gY-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,255,0),2)
        output.extend(groupOutput)

3.运行结果展示





 

4. 项目经验与总结

在这个项目中,我们通过使用OpenCV和相关库,成功实现了对信用卡上的数字进行自动识别。在这个过程中,我们涉及到了图像预处理、形态学处理、边缘查找和模板匹配等技术。以下是一些项目经验和总结:

  1. 图像预处理非常重要:在图像识别任务中,图像预处理是一个非常重要的步骤。适当的预处理可以提高数字识别的准确性,例如在本项目中,通过阈值化处理和轮廓查找,成功分离出了数字区域。

  2. 形态学处理的应用:形态学处理是图像处理中常用的技术,可以用来提取图像的特定结构或形状。在信用卡图像处理中,通过形态学处理成功提取出了信用卡号码的区域。

  3. 模板匹配的局限性:本项目中使用了模板匹配的方法对数字进行识别,虽然简单且有效,但模板匹配对图像的光照和尺度变化敏感。在实际应用中,可能需要更加复杂的算法来提高数字识别的准确性。

  4. 数据集的重要性:如果要将此项目用于实际应用,建议使用更大规模和多样化的信用卡图像数据集进行训练和测试,以提高数字识别的泛化能力。

  5. opencv函数变动:在opencv4及之后的版本中,findContours函数的返回值变成了两个,一个为roi的轮廓信息,另一个为层次信息。

  6. 参数修改:文章中对于数字的识别部分需要根据实际情况进行合理修改,否则可能无法检测到信用卡数字!

总体来说,这个项目对于理解图像处理和数字识别的基本原理是非常有帮助的。通过实际动手实现,可以更深入地理解算法的原理和局限性。希望本博客能帮助到其他对图像处理感兴趣的程序员,欢迎交流和指正。谢谢阅读!

项目借鉴总体流程与方法讲解_哔哩哔哩_bilibili。如有疑问或意见,请在评论区留言,我将尽快回复。谢谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值