OpenCV---xx1(信用卡卡号识别项目实战)

信用卡卡号识别项目实战

本项目通过模板匹配的方式 来对一张信用卡的卡号进行识别读取并在
原图中相应位置 展示出来

原理分析

1 对模板进行分割排序和标签标定
2 信用卡进行一系列处理后 得到相应位置的数字
3 将数字和模板进行 模板匹配 取最大值作为结果返还
4 将数字在相对位置画出

代码详解

import cv2 as cv

该函数将数字圈出并输出相应的数字

def draw_num(img, num, x, y, w, h):
cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1, 8)
cv.putText(img, str(num), (x, y), cv.FONT_HERSHEY_SIMPLEX, 0.65, (0, 255 ,0), 2)

return img

模板的轮廓是无序的 该函数来对模板进行排序 x最小的为1 并返回排序后的轮廓的x,y,w,h

def sort_num(contours):
rect_num = [(cv.boundingRect(i), i) for i in contours]

sort_temp = sorted(rect_num, key=lambda x: x[0][0])

sort_num = [i[0] for i in sort_temp]

return sort_num

if name == 'main':
img_temp = cv.imread(r'.\use_img\img_3.png')
pre_img = cv.imread(r".\use_img\img.png")

模板图像灰度化

img_gray = cv.cvtColor(img_temp, cv.COLOR_BGR2GRAY)
cv.imshow('img_gray', img_gray)
# 模板图像二值化
_, img_bin = cv.threshold(img_gray, 10, 255, cv.THRESH_BINARY_INV)
cv.imshow('img_temp', img_bin)
# 拿到模板的各个数字的轮廓
contours, hierarchy = cv.findContours(img_bin, 0, 2)
# 画出来看一下
# cv.drawContours(img_temp, contours, -1, (0, 0, 255), 2, 8)
# cv.imshow('img_contours', img_temp)

print(contours)

对轮廓进行排序 并返回排序好的轮廓
contours_sort = sort_num(contours)
# print(contours_sort)
对轮廓用字典进行标定其代表的数字 并且重置大小
num_dict = {contours_sort.index(i) + 1: cv.resize(img_bin[i[1]:i[1] + i[3], i[0]:i[0] + i[2]], (50, 100)) for i in
contours_sort}
zero_coord = contours_sort[-1]
num_dict[0] = cv.resize(
img_bin[zero_coord[1]:zero_coord[1] + zero_coord[3], zero_coord[0]:zero_coord[0] + zero_coord[2]], (50, 100))

图像处理 创建卷积核并且转换为灰度后高斯滤波

rect_kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 12))
pre_gray = cv.cvtColor(pre_img, cv.COLOR_BGR2GRAY)
pre_gray = cv.GaussianBlur(pre_gray, (5, 5), 20)
cv.imshow('gray', pre_gray)
# 顶帽操作 突出更明亮的区域
pre_tophat = cv.morphologyEx(pre_gray, cv.MORPH_TOPHAT, rect_kernel)
cv.imshow('pre_tophat', pre_tophat)

边缘检测 拿到图像

pre_canny = cv.Canny(pre_tophat, 15, 200, apertureSize=3)
pre_canny = cv.convertScaleAbs(pre_canny)
cv.imshow('tes1', pre_canny)

print(pre_canny)

闭运算

close_kernel = cv.getStructuringElement(cv.MORPH_RECT, (55, 15))
pre_close = cv.morphologyEx(pre_canny, cv.MORPH_CLOSE, close_kernel)
cv.imshow('tes2', pre_close)

找轮廓

contours2, hierarchy2 = cv.findContours(pre_close, 0, 2)

cv.imshow('cont_in_pre_img',cv.drawContours(pre_img.copy(), contours2, -1, (255, 0, 0), 5, 8))

conts = []

res_coor = []

将符合待检测的轮廓添加到列表

for i in contours2:
x, y, w, h = cv.boundingRect(i)

if 350 < y < 400:
conts.append((x, y, w, h))

拿到大块轮廓

for i in conts:
x, y, w, h = i
test_img = pre_gray[y - 5:y + h + 5, x - 5:x + w + 5]

大块轮廓二值化

_, test_img_bin = cv.threshold(test_img, 200, 255, cv.THRESH_BINARY)
conts_num, hierarchy3 = cv.findContours(test_img_bin, 0, 2)

拿到大轮廓里的小轮廓 一个个数字

for j in conts_num:
# 这个是在大轮廓的坐标 不是在pre_img的坐标
x1, y1, w1, h1 = cv.boundingRect(j)

be_test = cv.resize(test_img_bin[y1:y1 + h1, x1:x1 + w1], (50, 100))

score_temp = 0

匹配并存储结果

res = None
for z in num_dict:
score = cv.matchTemplate(be_test, num_dict[z], cv.TM_CCOEFF)
if score > score_temp:
res = z
score_temp = score

res_coor.append((res, (x + x1, y, w1, h1)))

将结果和位置画在pre_img

img = pre_img.copy()
for i in res_coor:
img = draw_num(img, i[0], *i[1])

cv.imshow('res', img)
cv.waitKey(0)
cv.destroyAllWindows()

结果展示

image
展示二值化后的模板和排序后的数字1的模板

image
灰度运算

image
顶帽运算

image
边缘检测

image
闭运算

image
轮廓

image
最终结果

posted @ 2022-03-26 17:06  cc学习之路  阅读(312)  评论(2)    收藏  举报