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

![字体文件](https://img-blog.csdnimg.cn/3a16c87cf4d34aceb0778c4b20ddadb2.png#pic_center![e5628b04eb93564c23ed0f58a360a10.png](https://file.jishuzhan.net/article/1731663776375115777/72fcac8d77f47079050bbaffbc110b3b.webp)

python 复制代码
import cv2
import numpy as np


def 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 = False
    i = 0
    if method == 'right-to-left' or method == 'bottom-to-top':
        reverse = True
    if method == 'bottom-to-top' or method == 'top-to-bottom':
        i = 1

    boundingBoxes = [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")
相关推荐
这个男人是小帅20 分钟前
【GAT】 代码详解 (1) 运行方法【pytorch】可运行版本
人工智能·pytorch·python·深度学习·分类
__基本操作__22 分钟前
边缘提取函数 [OPENCV--2]
人工智能·opencv·计算机视觉
这是一个图像24 分钟前
从opencv-python入门opencv--图像处理之图像滤波
图像处理·opencv·计算机视觉·中值滤波·高斯滤波·双边滤波·图像滤波
Doctor老王26 分钟前
TR3:Pytorch复现Transformer
人工智能·pytorch·transformer
热爱生活的五柒26 分钟前
pytorch中数据和模型都要部署在cuda上面
人工智能·pytorch·深度学习
HyperAI超神经2 小时前
【TVM 教程】使用 Tensorize 来利用硬件内联函数
人工智能·深度学习·自然语言处理·tvm·计算机技术·编程开发·编译框架
扫地的小何尚4 小时前
NVIDIA RTX 系统上使用 llama.cpp 加速 LLM
人工智能·aigc·llama·gpu·nvidia·cuda·英伟达
埃菲尔铁塔_CV算法6 小时前
深度学习神经网络创新点方向
人工智能·深度学习·神经网络
艾思科蓝-何老师【H8053】7 小时前
【ACM出版】第四届信号处理与通信技术国际学术会议(SPCT 2024)
人工智能·信号处理·论文发表·香港中文大学
weixin_452600697 小时前
《青牛科技 GC6125:驱动芯片中的璀璨之星,点亮 IPcamera 和云台控制(替代 BU24025/ROHM)》
人工智能·科技·单片机·嵌入式硬件·新能源充电桩·智能充电枪