openCV实践项目:银行卡卡号识别_thresh,ref= cv2


![](https://img-blog.csdnimg.cn/fffeec29f89b4f2b989740e2536cfa92.png)


* 遍历对这10个轮廓,做外接矩形,对外接矩形区域在二值化图ref上做切片,即把他们一个个抠出来,保存在 digits 字典中。



digits = {}

遍历每一个轮廓

for (i, c) in enumerate(refCnts):
# 计算外接矩形并且resize成合适大小
(x, y, w, h) = cv2.boundingRect©
roi = ref[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))

# 每一个数字对应每一个模板,此时模板中的10个数字分别被保存到了字典中
digits[i] = roi


#### 3.1.2 处理银行卡


* 初始化卷积核,读取输入图像。



初始化卷积核

rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

读入银行卡

image = cv2.imread(‘./images/credit_card_01.png’)


![](https://img-blog.csdnimg.cn/1e95a03b6d454a88805b7cb48e3d9027.png)


* 统一大小,这里建议让它变小一点,处理像素少一点,后面闭运算让其模糊也方便一些。



set_width = 300 # 自己设定 这里我统一了宽度
rate = set_width/image.shape[:2][1]
image = cv2.resize(image,(0,0),fx=rate,fy=rate)


* 转为灰度图



同样也可以在第一步完成

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


![](https://img-blog.csdnimg.cn/b0cefde679964fbfb87b725d01a75e2a.png)


* 礼帽,突出更明亮的区域,可以看到此时银行卡后面的花纹基本已经消失了。 。



tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)


![](https://img-blog.csdnimg.cn/c4a126ecd79943c9b1e188acbad49b63.png)


* 梯度运算,这里使用Sobel算子,只进行了x方向计算。前面的礼帽操作是的我们梯度运算结果更干净些。



ksize=-1相当于用3*3的

gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)

gradX = np.absolute(gradX) # 绝对值,白-黑 黑-白

或者写为 cv2.convertScaleAbs(sobelx)

归一化处理

(minVal, maxVal) = (np.min(gradX), np.max(gradX))

gradX与最小值之间的距离占区间长度的几分之几

gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype(“uint8”)


![](https://img-blog.csdnimg.cn/e555dbb1653043bf8af571e1bdfa8ab4.png)


* 闭运算、二值化、闭运算



闭运算 把银行卡卡号那里弄模糊

gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)

二值化,用于之后轮廓检测。

thresh = cv2.threshold(gradX, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

再来一个闭操作

thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)


![](https://img-blog.csdnimg.cn/423cc2d1352a41a0961f0946621290ce.png)


* 轮廓检测



threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
‘’’
cur_img = image.copy()
cv2.drawContours(cur_img, threshCnts, -1, (0, 0, 255), 3)
cv_show(‘img’, cur_img)
‘’’


![](https://img-blog.csdnimg.cn/2323dfd3e3af49e7965573a69328d1f6.png)


* 遍历所有轮廓,得到想要的四组数字,并排序。



locs = []

遍历轮廓

for (i, c) in enumerate(threshCnts):
# 计算矩形
(x, y, w, h) = cv2.boundingRect©
ar = w / float(h)

# 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
if ar > 2.5 and ar < 4.0:

    if (w > 40 and w < 55) and (h > 10 and h < 20):
        # 符合的留下来
        locs.append((x, y, w, h))

将符合的这四组轮廓按x从左到右排序

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


* 遍历这四组数



output = []

遍历每一个轮廓中的数字

for (i, (gX, gY, gW, gH)) in enumerate(locs):
groupOutput = []

# 根据坐标提取每一个组
group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
cv_show('group', group)
# 预处理
group = cv2.threshold(group, 0, 255,
                      cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('group', group)
# 计算每一组的轮廓
# group_, 
digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
                                                cv2.CHAIN_APPROX_SIMPLE)

# 就是个排序 真正的顺序我们都知道,可以自己用sort函数
digitCnts = contours.sort_contours(digitCnts,
                                   method="left-to-right")[0]

# 计算每一组中的每一个数值
for c in digitCnts:
    # 找到当前数值的轮廓,resize成合适的的大小
    (x, y, w, h) = cv2.boundingRect(c)
    roi = group[y:y + h, x:x + w]
    roi = cv2.resize(roi, (57, 88))
    cv_show('roi', roi)

    # 计算匹配得分
    scores = []

    # 在模板中计算每一个得分  字典digits记录了模板0-9
    for (digit, digitROI) in digits.items():
        # 模板匹配
        result = cv2.matchTemplate(roi, digitROI,
                                   cv2.TM_CCOEFF)
        (_, score, _, _) = cv2.minMaxLoc(result)
        scores.append(score)

    # 得到最合适的数字,这里用的匹配方法对应得分越大越好。
    groupOutput.append(str(np.argmax(scores)))
    
# 画出来
cv2.rectangle(image, (gX - 5, gY - 5),
              (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
cv2.putText(image, "".join(groupOutput), (gX, gY - 15),
            cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)

# 得到结果
output.extend(groupOutput)

![](https://img-blog.csdnimg.cn/cd663ab07fd44939b504652dc614c3ba.png)


* 输出结果



print(“Credit Card #: {}”.format(“”.join(output)))

cv_show(“Image”, image)



Credit Card #: 4000123456789010


### 3.2 完整代码  直接copy


我去掉了图片展示,直接输出文本结果。 



import cv2
import numpy as np
from imutils import contours # 排序操作,也可以不用。

绘图展示

def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()

读取一个模板图像

img = cv2.imread(‘ocr_a_reference.png’, )

灰度图

ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

二值图像

ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]

轮廓检测

refCnts, hierarchy = cv2.findContours(ref, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

排序(倒序操作) 得到正序0-9的轮廓

refCnts = sorted(refCnts, key=lambda b: b[0][0][0], reverse=False)

digits = {}

遍历每一个轮廓

for (i, c) in enumerate(refCnts):
# 计算外接矩形并且resize成合适大小
(x, y, w, h) = cv2.boundingRect©
roi = ref[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
# 每一个数字对应每一个模板,此时模板中的10个数字分别被保存到了字典中
digits[i] = roi

初始化卷积核

rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

读入银行卡

image = cv2.imread(‘./images/credit_card_01.png’)

统一大小,这里建议让它变小一点,处理像素少一点,后面闭运算让其模糊也方便一些。

set_width = 300 # 自己设定 这里我统一了宽度
rate = set_width / image.shape[:2][1]
image = cv2.resize(image, (0, 0), fx=rate, fy=rate)

转为灰度图

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

礼帽,突出更明亮的区域

tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)

梯度运算,这里使用Sobel算子,只进行了x方向计算。前面的礼帽操作是的我们梯度运算结果更干净些。

ksize=-1相当于用3*3的

gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)

gradX = np.absolute(gradX) # 绝对值,白-黑 黑-白

或者写为 cv2.convertScaleAbs(sobelx)

归一化处理

(minVal, maxVal) = (np.min(gradX), np.max(gradX))

gradX与最小值之间的距离占区间长度的几分之几

gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype(“uint8”)

闭运算 把银行卡卡号那里弄模糊

gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)

二值化,用于之后轮廓检测。

thresh = cv2.threshold(gradX, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

再来一个闭操作

thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)

轮廓检测

threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)

locs = []

遍历轮廓

for (i, c) in enumerate(threshCnts):
# 计算矩形
(x, y, w, h) = cv2.boundingRect©
ar = w / float(h)

# 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
if ar > 2.5 and ar < 4.0:

    if (w > 40 and w < 55) and (h > 10 and h < 20):
        # 符合的留下来
        locs.append((x, y, w, h))

将符合的这四组轮廓按x从左到右排序

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

遍历这四组数

output = []

遍历每一个轮廓中的数字

for (i, (gX, gY, gW, gH)) in enumerate(locs):
groupOutput = []

# 根据坐标提取每一个组
group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
# 预处理
group = cv2.threshold(group, 0, 255,
                      cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 计算每一组的轮廓
# group_,
digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
                                        cv2.CHAIN_APPROX_SIMPLE)

# 就是个排序 真正的顺序我们都知道,可以自己用sort函数
digitCnts = contours.sort_contours(digitCnts,
                                   method="left-to-right")[0]

# 计算每一组中的每一个数值
for c in digitCnts:
    # 找到当前数值的轮廓,resize成合适的的大小
    (x, y, w, h) = cv2.boundingRect(c)
    roi = group[y:y + h, x:x + w]
    roi = cv2.resize(roi, (57, 88))

    # 计算匹配得分
    scores = []

    # 在模板中计算每一个得分  字典digits记录了模板0-9
    for (digit, digitROI) in digits.items():
        # 模板匹配
        result = cv2.matchTemplate(roi, digitROI,
                                   cv2.TM_CCOEFF)
        (_, score, _, _) = cv2.minMaxLoc(result)
        scores.append(score)

    # 得到最合适的数字,这里用的匹配方法对应得分越大越好。
    groupOutput.append(str(np.argmax(scores)))

# 画出来
cv2.rectangle(image, (gX - 5, gY - 5),
              (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
cv2.putText(image, "".join(groupOutput), (gX, gY - 15),

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

tText(image, “”.join(groupOutput), (gX, gY - 15),

[外链图片转存中…(img-8e3YzMfk-1714416525258)]
[外链图片转存中…(img-BooeET70-1714416525259)]
[外链图片转存中…(img-G2BEo1UU-1714416525260)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值