使用opencv的matchTemplate进行银行卡卡号识别

![字体文件](https://img-blog.csdnimg.cn/3a16c87cf4d34aceb0778c4b20ddadb2.png#pic_centere5628b04eb93564c23ed0f58a360a10.png

import cv2
import numpy as npdef show_img(img, name="temp"):img = cv2.resize(img, (0, 0), fx=3, fy=3)cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()def show_img_normal(img, name="temp"):img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()# 排序方法
def sort_contours(cnts, method='left-to-right'):reverse = Falsei = 0if method == 'right-to-left' or method == 'bottom-to-top':reverse = Trueif method == 'bottom-to-top' or method == 'top-to-bottom':i = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts](cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][i], reverse=reverse))return (cnts, boundingBoxes)# 读取图像
number_o = cv2.imread("./source/e5628b04eb93564c23ed0f58a360a10.png")
# 转灰度图
number_gary = cv2.cvtColor(number_o, cv2.COLOR_BGR2GRAY)
# 二值化操作
_, number_threshold = cv2.threshold(number_gary, 100, 255, cv2.THRESH_BINARY_INV)
# show_img(number_threshold, "number_threshold")
# 轮廓检测,只检测外轮廓,绘制到原图上
contours, hierarchy = cv2.findContours(number_threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
number_contours = cv2.drawContours(number_o, contours, -1, (0, 255, 0), 1)
# show_img(number_contours, "number_contours")# 绘制所有轮廓的方形边界
number_boundingRect = number_o.copy()
number_imgs = []
contours = sort_contours(contours)[0]
# contours.sort_cont(key=cv2.INTER_AREA, reverse=True)
for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)cv2.rectangle(number_boundingRect, (x, y), (x + w, y + h), (0, 0, 255), 1)# 显示每一个模板,作为单独图片number_one = number_threshold[y: y + h, x:x + w]number_one = cv2.resize(number_one, (35, 50))number_imgs.append(number_one)# show_img(number_one, "every")# 显示每一个模板,所有.展示外边框信息数据
show_img(number_boundingRect, "number_boundingRect")im_o = cv2.rotate(cv2.imread("./source/data/1.jpg"), cv2.ROTATE_90_COUNTERCLOCKWISE)
im_gary = cv2.cvtColor(im_o, cv2.COLOR_BGR2GRAY)
# show_img_normal(im_gary, "im_gary")# 构建卷积核
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 2))# 执行礼帽操作,高亮一下有效信息
im_tophat = cv2.morphologyEx(im_gary, cv2.MORPH_TOPHAT, kernel=kernel2, iterations=1)
# show_img_normal(im_tophat, "im_tophat")# 闭操作,将临近相似区域连起来
im_close = cv2.morphologyEx(im_tophat, cv2.MORPH_CLOSE, kernel2, iterations=8)
# show_img_normal(im_close, "im_close")# 二值化,分离信息
_, im_threshold = cv2.threshold(im_close, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# show_img_normal(im_threshold, "im_threshold")# 中值滤波去除噪音点
im_medianBlur = cv2.medianBlur(im_threshold, 9)
# show_img_normal(im_medianBlur, "im_medianBlur")# 再执行闭操作,连起来相似区域
im_close2 = cv2.morphologyEx(im_medianBlur, cv2.MORPH_CLOSE, kernel2, iterations=2)
# show_img_normal(im_close2, "im_close2")# 执行轮廓提取
contours, hierarchy = cv2.findContours(im_close2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)validCnt = []
# 所有的边框边界
im_boundingRect_all = cv2.cvtColor(im_close2.copy(), cv2.COLOR_GRAY2BGR)
im_boundingRect_valid = cv2.cvtColor(im_close2.copy(), cv2.COLOR_GRAY2BGR)# 记录所有的面积数据
area = np.empty((len(contours),))# 遍历一下,填充面积,后面算平均值和标准差,来过滤过小数据
for index, cnt in enumerate(contours):area[index] = cv2.contourArea(cnt)mean = np.mean(area)
std = np.std(area)for cnt in contours:x, y, w, h = cv2.boundingRect(cnt)# 计算面积areaX = cv2.contourArea(cnt)# 计算长宽比aspectRatio = w / h# 绘制长宽比和值cv2.rectangle(im_boundingRect_all, (x, y), (x + w, y + h), (0, 255, 0), 2)cv2.putText(im_boundingRect_all, f"{aspectRatio:.3f}", (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)# 只有指定比例和面积不是过小的 > mean + std的,选出来if (2.8 < aspectRatio < 3.2 or 4.2 < aspectRatio < 5.8 or 8 < aspectRatio < 10) and (areaX > mean - 0 * std):validCnt.append(cnt)cv2.rectangle(im_boundingRect_valid, (x, y), (x + w, y + h), (0, 255, 255), 2)cv2.putText(im_boundingRect_valid, f"{aspectRatio:.3f}", (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 255), 2)# show_img_normal(im_boundingRect_all, "im_boundingRect_all")
# show_img_normal(im_boundingRect_valid, "im_boundingRect_valid")# 将有效区域定义出来ROI区域,进行边缘检测,拆分单个字符
for cnt in validCnt:x, y, w, h = cv2.boundingRect(cnt)# 显示roi区域im_roi = im_gary[y - 15:y + h + 5, x - 15:x + w + 5]# show_img(im_roi)# 二值化_, im_roi_threshold = cv2.threshold(im_roi, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)# show_img(im_roi_threshold, "im_roi_threshold")# 闭操作合并一些边界k = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))im_roi_close = cv2.morphologyEx(im_roi_threshold, cv2.MORPH_CLOSE, k, iterations=2)# show_img(im_roi_close, "im_roi_close")# 轮廓检测im_roi_bound = cv2.cvtColor(im_roi.copy(), cv2.COLOR_GRAY2BGR)im_roi_contours, hierarchy = cv2.findContours(im_roi_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)im_roi_contours = sort_contours(im_roi_contours)[0]# im_roi_bound = im_roi_close.copy()for cnt_roi in im_roi_contours:xr, yr, wr, hr = cv2.boundingRect(cnt_roi)cv2.rectangle(im_roi_bound, (xr, yr), (xr + wr, yr + hr), (255, 0, 0), 1)im_roi_close_one = cv2.resize(im_roi_close[yr: yr + hr, xr:xr + wr], (35, 50))# 显示切分出来的单个数字# show_img(im_roi_close_one, "im_roi_close_one")# 和10个数字比scores = []for number_img_one in number_imgs:score = cv2.matchTemplate(im_roi_close_one, number_img_one, cv2.TM_CCOEFF_NORMED)scores.append(score)maxIndex = scores.index(max(scores))cv2.putText(im_o, str(maxIndex), (x + xr, y + yr), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 255), 2)cv2.putText(im_roi_bound, str(maxIndex), ( xr, yr + 10), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 255), 1)# 显示切分的轮廓# show_img(im_roi_bound, "im_roi_bound")
show_img_normal(im_o, "im_o")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/224935.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神奇的世界(高斯核是唯一可以产生多尺度空间的线性核研究总结,两个高斯公式的联系,和推导)

放大缩小其实在现实世界中不存在。 也就是说尺度是不存在的。 比如树的长大&#xff0c;人的长大&#xff0c;从来就不是放大能解释的。 但你发现&#xff0c;这种事情存在于人的眼睛当中&#xff0c;光线真是神奇的东西。 但现实的东西是不存在放大缩小的&#xff0c;只有…

DjiTello + YoloV5的无人机的抽烟检测

一、效果展示 注&#xff1a;此项目纯作者自己原创&#xff0c;创作不易&#xff0c;不经同意不给予搬运权限&#xff0c;转发前请联系我&#xff0c;源码较大需要者评论获取&#xff0c;谢谢配合&#xff01; 1、未启动飞行模型无人机的目标检测。 DjiTello YOLOV5抽烟检测 …

【深入剖析K8s】容器技术基础(三):深入理解容器镜像 文件角度

容器里的进程‘看到’’的文件系统 可能你立刻就能想到,这应该是一个关于MountNamespace的问题:容器里的应用进程理应‘看到”一套完全独立的文件系统这样它就可以在自己的容器目录&#xff08;比如 /tmp&#xff09;下进行操作’而完全不会受宿主机以及其他容器的影响。 容器…

94.STM32外部中断

目录 1.什么是 NVIC&#xff1f; 2.NVIC寄存器 3.中断优先级 4.NVIC的配置 设置中断分组​编辑 配置某一个中断的优先级 5.什么是EXTI 6.EXTI和NVIC之间的关系 7.SYSCFG 的介绍 1.什么是 NVIC&#xff1f; NVIC是一种中断控制器&#xff0c;主要用于处理 ARM Cort…

美国高防云服务器的优劣势分析(相比普通云服务器)

在当前数字化时代&#xff0c;云服务器已经成为企业和个人进行在线业务的重要基础设施。而在选择云服务器时&#xff0c;很多人会面临一个问题&#xff1a;是选择普通云服务器还是高防云服务器?本文将从多个方面来分析美国高防云服务器相比普通云服务器的优势和劣势。 我们来看…

【APUE】进程间通信

目录 一、管道 1.1 匿名管道 1.2 命名管道 二、XSI IPC 2.1 概述 2.2 消息队列 2.2.1 msgget 2.2.2 msgsnd 2.2.3 msgrcv 2.2.4 msgctl 2.2.5 代码示例 2.3 信号量数组 2.3.1 semget 2.3.2 semop 2.3.3 semctl 2.3.4 代码示例 2.3 共享内存 2.3.1 shmget…

【1】AR Tag 在ros中的使用

1.定义 AR Tag 是一种用于增强现实&#xff08;AR&#xff09;应用中的视觉标记&#xff0c;用于跟踪和定位虚拟物体在现实世界中的位置。 AR Tag由黑白正方形图像表示&#xff0c;图像内部有黑色边框中的某些图案。它与我们经常用到的二维码长得类似&#xff0c;原理其实也一…

【序列推荐】MAN:跨领域顺序推荐的混合注意网络

#论文题目&#xff1a;MAN&#xff1a;Mixed Attention Network for Cross-domain Sequential Recommendation&#xff08;跨领域顺序推荐的混合注意网络&#xff09; #论文地址&#xff1a;https://dl.acm.org/doi/10.1145/3543507.3583278 #论文源码开源地址&#xff1a;http…

Java核心知识点整理大全19-笔记

目录 14.1.5.2. MemStore 刷盘 全局内存控制 MemStore 达到上限 RegionServer 的 Hlog 数量达到上限 手工触发 关闭 RegionServer 触发 Region 使用 HLOG 恢复完数据后触发 14.1.6.HBase vs Cassandra 15. MongoDB 15.1.1. 概念 15.1.2. 特点 16. Cassandra 16.1.1…

爬虫必学:Java创建代理ip池详细教程

目录 一、引言 二、代理IP池的基本概念 三、Java创建代理IP池的步骤 1、引入相关依赖 2、创建代理IP池类 3、代理IP的获取与释放 四、代理IP的获取方式 五、总结 一、引言 网络爬虫是自动从网站抓取信息的程序。在爬虫运行过程中&#xff0c;经常遇到的问题之一是目标…

应用密码学期末复习(1)

学习资料 应用密码学总结_应用密码学知识点总结-CSDN博客 应用密码学期末复习知识点总结_5的36次方mod97__PriDe的博客-CSDN博客 【密码学】密码学期末考试速成课&#xff0c;不挂科&#xff01;&#xff01;#高数帮_哔哩哔哩_bilibili 目录 学习资料 第一章 概述 1.1信息…

Linux基本指令汇总

本专栏内容为&#xff1a;Linux学习专栏&#xff0c;分为系统和网络两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握Linux。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;Linux从入门到精通 &#x1f69a;代码仓库&#xff1a;小…