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
最终结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值