招商银行信用卡卡号识别项目(第一篇),Python OpenCV 图像处理取经之旅第 53 篇

Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。本篇博客是这个系列的第 53 篇。
该系列文章导航参考:https://blog.csdn.net/hihell/category_10688961.html

学在前面

从本篇博客起,我们将实际完成几个小案例,第一个就是银行卡号识别,预计本案例将写 5 篇左右的博客才可以完成,一起加油吧。

本文的目标是最终获取一套招商银行卡,0~9 数字的图,对于下图的数字,我们需要提取出来,便于后续模板匹配使用。不过下图中找到的数字不完整,需要找到尽量多的卡片,然后补齐这些数字。

20210304134959294[1].png

提取卡片相关数字

先对上文中卡片中的数字进行相关提取操作,加载图片的灰度图,获取目标区域。在画板中模拟一下坐标区域,为了便于进行后续的操作。

20210304175041659[1].png

具体代码如下:

import cv2 as cv
import numpy as np
# 读取灰度图
src = cv.imread("./ka1.jpg", 0)

# 寻找卡号目标区域
roi = src[142:168, 42:360]
# cv.imshow("roi",roi)

获取到的图片如下,发现右侧边缘缺少一部分内容,对目标区域坐标进行微调。

20210304175256930[1].png

修改之后的代码如下,你如果使用的图片与橡皮擦不一致,注意进行修改。

# 寻找卡号目标区域
roi = src[142:168, 46:364]
cv.imshow("roi",roi)
20210304175438548[1].png

消除噪音,可以增加模糊卷积操作,分别测试均值模糊,中值模糊,高斯模糊效果。

# 模糊卷积操作
blur_roi = cv.blur(roi,(5,5))
cv.imshow("blur_roi",blur_roi)

med_roi = cv.medianBlur(roi,5)
cv.imshow("med_roi",med_roi)

gau_roi = cv.GaussianBlur(roi,(7,7),0)
cv.imshow("gau_roi",gau_roi)

测试不同的卷积核效果,选择一个合适的即可,我这里发现卷积核为 (7,7) 的时候,高斯模糊效果不错,可以去噪。

20210304180157993[1].png

接下来进行二值化操作。

# 对目标区域进行二值化操作
ret, thresh = cv.threshold(
    gau_roi, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("thresh", thresh)
20210304180741277[1].png

二值化处理完毕之后,发现还存在一些白色区域的点,需要去除掉,这里使用了形态学里面的腐蚀操作。

# 腐蚀
kernel = np.ones((3, 4), np.uint8)
dst = cv.erode(thresh, kernel=kernel)
20210304181149942[1].png

腐蚀之后在进行膨胀,让原有的数字区域变的明显,最后的图片是进行之后的效果,关于卷积核你可以自行调整。

# 腐蚀
kernel = np.ones((3, 4), np.uint8)
erode_dst = cv.erode(thresh, kernel=kernel)
cv.imshow("erode_dst", erode_dst)
# 膨胀
kernel = np.ones((4, 4), np.uint8)
dilate_dst = cv.dilate(erode_dst, kernel=kernel)
20210304181535870[1].png

下面进行外轮廓检测,检测之后发现恰好有 16 个轮廓,也就对应了 16 个数字区域。

# 检测外轮廓
# 只检测外轮廓
contours, hierarchy = cv.findContours(dilate_dst, cv.RETR_EXTERNAL,  cv.CHAIN_APPROX_SIMPLE)

print(len(contours))
20210304181754885[1].png

对轮廓面积进行一下输出,为了防止出现非目标区域,可以进行一下基本的判断,当罗阔面积大于 80 的时候才进行展示。

target_list = []
# 轮廓判断
for cnt in contours:

    # 轮廓面积
    area = cv.contourArea(cnt)
    print(area)
    if area > 79:
        target_list.append(cnt)

print(len(target_list))
20210304182005861[1].png

有这些参数之后,就可以对灰度图进行裁切了,基于外接矩形获取目标区域,我直接做了循环展示。

for index, cnt in enumerate(target_list):
    # 外接矩形
    x, y, w, h = cv.boundingRect(cnt)
    # 在二值化的图像上进行目标区域获取
    c_roi = roi[y:y+h, x:x+w]
    # 调整图像大小
    # big_roi = cv.resize(c_roi, dsize=(0, 0), fx=2, fy=2)
    # big_roi = cv.resize(c_roi, dsize=(0, 0))
    cv.imshow("big_roi"+str(index), c_roi)
    # cv.imwrite(f"./numbers/ka_{index}.png", big_roi)
2021030418294985[1].png

接下来放大图片对其进行保存即可,得到如下图片列表,至此,已经获取到 1、4、6、8 几个数字,下面在切换到另一张卡片,去获取其他数字即可,注意图片大小保持一致。

big_roi = cv.resize(c_roi, dsize=(42, 66))
# cv.imshow("c_roi"+str(index), c_roi)
cv.imwrite(f"./numbers/ka1_{index}.png", big_roi)
20210304210337194[1].png

新的图像注意调整目标区域,获取素材,已经获取到 1、2、4、5、6、7、8 几个数字

20210304210645735[1].png

反复迭代这个办法,知道 0~9 个数字获取完整,找到所有数字之后,对该文件夹中的所有文件进行二值化操作。

import cv2 as cv
import os

def walk_file(file):
    for root, dirs, files in os.walk(file):
        for f in files:
            file = os.path.join(root, f)
            # 读取灰度图
            basename = os.path.basename(file)
            filename = basename.split(".")[0]
            src = cv.imread(file, 0)
            ret, thresh = cv.threshold(src, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
            # cv.imshow("thresh", thresh)
            cv.imwrite(f"./numbers/001_{filename}_bit.png", thresh)
            cv.waitKey()
            cv.destroyAllWindows()

if __name__ == "__main__":
    walk_file("./numbers")

二值化之后,挑选出比较清晰的数字即可,如果发现存在不清楚的,可以在寻找资源进行提取,银行里面 8 真的是太多了。

20210304212631901[1].png

橡皮擦最后调整之后,得到的结果如下所示,信用卡卡号识别的第一步算是准备好了。


2021030421294819[1].png

橡皮擦的小节

今天也碰到了一些问题,最难的问题,就是颜色相近,提取不出来前面的数字。
希望今天的 1 个小时(貌似不太够)你有所收获,我们下篇博客见~

相关阅读


技术专栏

  1. Python 爬虫 100 例教程,超棒的爬虫教程,立即订阅吧
  2. Python 爬虫小课,精彩 9 讲

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,576评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,515评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,017评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,626评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,625评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,255评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,825评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,729评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,271评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,363评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,498评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,183评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,867评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,338评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,458评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,906评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,507评论 2 359

推荐阅读更多精彩内容