【opencv】信用卡号识别实验

发布于:2024-05-21 ⋅ 阅读:(179) ⋅ 点赞:(0)

实验环境:anaconda、jupyter notebook(其它的ide也行)

实验用的包:numpy、matplotlib、opencv

实验目标:

识别信用卡的卡号

信用卡图片:

数字模板图片:

一、包引入

import cv2
import matplotlib.pyplot as plt
import numpy as np

二、数字模板特征提取

图片二值化处理

template = cv2.imread('template.png')

# 灰度处理
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# 二值处理
ret,template_bin = cv2.threshold(template_gray,127,255,cv2.THRESH_BINARY_INV)

plt.imshow(template_bin, 'gray')
plt.show()

数字模板二值化处理.png

检测数字模板外轮廓

# 只检测外轮廓
binary, template_contours, hierarchy = cv2.findContours(template_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
template_copy = template.copy()

template_contours_img = cv2.drawContours(template_copy, template_contours, -1, (0,0,255),1)

plt.imshow(template_contours_img)
plt.show()

数字模板外轮廓.png

找到外接矩形

# 外接矩形
tangles = []
template_copy = template.copy()
for cnt in template_contours:
    x,y,w,h = cv2.boundingRect(cnt)
    tangles.append((x,y,w,h))
    template_copy = cv2.rectangle(template_copy, (x, y), (x + w, y + h), (0,255,0), 2)
plt.imshow(cv2.cvtColor(template_copy, cv2.COLOR_BGR2RGB))
plt.show()
# 根据x值狠狠排序
tangles.sort()
print(tangles)

数字模板外接矩形.png

通过外接矩形截取数字图片

# 拿到数字对应的图片
number_size = (50,100)
digits = {}
for i in range(len(tangles)):
    (x,y,w,h) = tangles[i]
    digits[i] = cv2.resize(template_bin[y:y+h, x: x+w], number_size)
    plt.subplot(1,10,1 + i)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(digits[i],'gray')
plt.show()

数字模板.png

三、信用卡卡面特征提取

初始化卷积核、处理卡片

# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

# 读入信用卡图片
card = cv2.imread('card.png')
# 处理为灰度图
card_gray = cv2.cvtColor(card, cv2.COLOR_BGR2GRAY)
# 处理为礼帽处理
card_tophat = cv2.morphologyEx(card_gray, cv2.MORPH_TOPHAT, rectKernel)

plt.imshow(card_tophat,'gray')
plt.show()

信用卡礼帽.png

对信用卡图片梯度处理

gradx = cv2.Sobel(card_tophat, ddepth=cv2.CV_32F, dx=1,dy=0, ksize=-1)
card_gradx = np.absolute(gradx)
(min_val,max_val) = (np.min(card_gradx), np.max(card_gradx))
card_gradx = (255 * ((card_gradx - min_val) / (max_val - min_val)))
card_gradx = card_gradx.astype('uint8')

plt.imshow(card_gradx,'gray')
plt.show()

信用卡梯度处理.png

把特征轮廓合成一片,方便提取

闭操作

card_closing = cv2.morphologyEx(card_gradx, cv2.MORPH_CLOSE,rectKernel)

plt.imshow(card_closing,'gray')
plt.show()

信用卡闭操作.png

二值化

# 二值化,自动判断
ret,card_bin = cv2.threshold(card_closing,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)

plt.imshow(card_bin,'gray')
plt.show()

信用卡二值化处理.png

膨胀操作

# 膨胀操作,加强卡号特征
card_dilate = cv2.dilate(card_bin, rectKernel, iterations=1)

plt.imshow(card_dilate,'gray')
plt.show()

信用卡膨胀.png

获取外轮廓

# 检测外轮廓
binary, card_contours, hierarchy = cv2.findContours(card_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
card_copy = card.copy()

card_contours_img = cv2.drawContours(card_copy, card_contours, -1, (0,0,255),2)

plt.imshow(cv2.cvtColor(card_contours_img,cv2.COLOR_BGR2RGB))
plt.show()

此时拿到的外轮廓有很多不需要的地方

信用卡外轮廓.png

获取需要的外轮廓

card_copy = card.copy()
locs = []
for (i, sit) in enumerate(card_contours):
    (x,y,w,h) = cv2.boundingRect(sit)
    ar = w / float(h)
    if ar > 2.5 and ar < 4.0:
        if 65 < w < 70 and 15 < h < 25:
            locs.append((x,y,w,h))
locs.sort()
for (x,y,w,h) in locs:
    card_copy = cv2.rectangle(card_copy, (x, y), (x + w, y + h), (0,255,0), 2)
    plt.imshow(cv2.cvtColor(card_copy, cv2.COLOR_BGR2RGB))
plt.show()

信用卡卡号外轮廓提取.png

四、卡号识别

output = []
card_copy = card.copy()
for (i,(x,y,w,h)) in enumerate(locs):
    group_output = []
    # 获取每组卡号
    group = card_gray[y - 5 : y + h + 5, x - 5 : x + w + 5]
    # 转为二值图像
    ret, group = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    # 外轮廓检测
    binary, group_contours, hierarchy = cv2.findContours(group, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

    data_sites = []
    for data_sit in group_contours:
        data_sites.append(cv2.boundingRect(data_sit))
    data_sites.sort()

    for (gx, gy, gw, gh) in data_sites:
        data = cv2.resize(group[gy : gy + gh, gx : gx + gw], number_size)
        scores = []
        # 计算分数
        for (digit, digit_img) in digits.items():
            result = cv2.matchTemplate(data, digit_img, cv2.TM_CCOEFF_NORMED)
            (_,score,_,_) = cv2.minMaxLoc(result)
            scores.append(score)

        group_output.append(str(np.argmax(scores)))
        cv2.rectangle(card_copy,(x - 5, y - 5), (x + w +5, y + h + 5), (0,255,0),2)
        cv2.putText(card_copy, "".join(group_output), (x, y - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0,0,255),2)

    output.extend(group_output)

plt.imshow(cv2.cvtColor(card_copy, cv2.COLOR_BGR2RGB))
plt.show()
print(output)

成功识别卡号

信用卡卡号识别.png


网站公告

今日签到

点亮在社区的每一天
去签到