opencv+python学习day02: 信用卡数字识别

跟着b站教程学习p36-p40:
https://www.bilibili.com/video/BV1RQ4y1R7M6?p=40
感觉意义不大,一般用不到这些东西。
抄的视频内容,本来不该写原创,但是不想联系作者,而且链接不知该怎么放,联系侵权自删
import

import imutils
import argparse
import cv2 as cv
import myutils
import numpy as np

能import的代码绝不自己写
下载的myutils中没有conunders,所以自己抄了个

def sort_contours(cnt, method="left-to-right"):
    reverse = False
    i = 0

    if method == "left-to-right" or method == "bottom-to-top":
        i = 1
    boundingBoxes = [cv.boundingRect(c) for c in cnt]
    # 用一个最小的矩形,将找到的形状包起来x,y,h,w
    (cnt, boundingBoxes) = zip(*sorted(zip(cnt, boundingBoxes), key=lambda b: b[i], reverse=reverse))
    return cnt, boundingBoxes

框架就不细分了,直接上整体的代码,不过也都是跟着教程打上去的,没啥自己写的东西。

"""
配置参数:右键 -configurations-parameters:
--image images/credit_test.png   # 测试图片
--template  images/credit_mo.png   # 母版
"""
# 设置参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="test image path")
ap.add_argument("-t", "--template", required=True, help="mother image path")
args = vars(ap.parse_args())

# 指定信用卡类型
FIRST_NUMBER = {
    "3": "American Express",
    "4": "Visa",
    "5": "MasterCard",
    "6": "Discover Card"
}


# 绘图展示
def cv_show(name, src_img):
    cv.imshow(name, src)
    cv.waitKey(0)
    cv.destroyAllWindows()


src = cv.imread(args["template"])  # 读取一个模板图像
ref = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ref = cv.threshold(ref, 10, 255, cv.THRESH_BINARY_INV)[1]  # 二值化
# 计算轮廓
refCnt, hierarchy = cv.findContours(ref.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(src, refCnt, -1, (0, 0, 255), 1)  # 绘制轮廓
#  轮廓排序
refCnt = myutils.sort_contours(refCnt, method="left-to-right")[0]  # 排序,从左到右,从上到下,import
digits = {}

# 模板制作,i表示轮廓索引,c表示找到的轮廓
for (i, c) in enumerate(refCnt):
    # 计算外接矩形并且resize成合适大小 ,x,y表示矩形的起点坐标,w,h,表示矩形的长宽
    (x, y, w, h) = cv.boundingRect(c)
    roi = ref[y:y + h, x:x + w]
    roi = cv.resize(roi, (57, 88))
    digits[i] = roi

# 初始化卷积核,核大小自己指定,与任务有关
rectKernel = cv.getStructuringElement(cv.MORPH_RECT, (9, 3))
sqKernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))

# 读取输入图像,预处理
img = cv.imread(args["image"])  # ???

# 重新设置输入图片的大小
image = imutils.resize(img, width=300)
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

# 礼帽操作,突出更明亮的区域
top_hat = cv.morphologyEx(gray, cv.MORPH_TOPHAT, rectKernel)
# sobel 算子,只有x效果比x+y效果好
gradX = cv.Sobel(top_hat, ddepth=cv.CV_32F, dx=1, dy=0,  # -1,3*3
                 ksize=-1)
gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")
# 通过闭操作(先膨胀,再腐蚀)将数字连在一起
gradX = cv.morphologyEx(gradX, cv.MORPH_CLOSE, rectKernel)
# OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv.threshold(gradX, 0, 255,
                      cv.THRESH_BINARY | cv.THRESH_OTSU)[1]
# 闭操作
thresh = cv.morphologyEx(thresh, cv.MORPH_CLOSE, sqKernel)
threshCnt, hierarchy = cv.findContours(thresh.copy(), cv.RETR_EXTERNAL,
                                       cv.CHAIN_APPROX_SIMPLE)
cnt = threshCnt
cur_img = image.copy()

# 画出找到的待匹配图像轮廓
cv.drawContours(cur_img, cnt, -1, (0, 0, 255), 3)
# 存储符合条件的轮廓信息
loc = []
# 遍历轮廓
for (i, c) in enumerate(cnt):
    # 计算矩形
    (x, y, w, h) = cv.boundingRect(c)
    ar = w / float(h)
    # 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
    if 2.5 < ar < 4.0:
        if (40 < w < 55) and (10 < h < 20):
            # 符合的留下来
            loc.append((x, y, w, h))
# 将符合的轮廓从左到右排序
loc = sorted(loc, key=lambda x1: x1[0])
output = []

# 遍历每一个轮廓中的数字,索引及详细信息
for (i, (gX, gY, gW, gH)) in enumerate(loc):
    groupOutput = []
    # 根据坐标提取每一个组,将每一组的轮廓适当的上下左右均扩大
    group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
    # 预处理,自动进行分割
    group = cv.threshold(group, 0, 255,
                         cv.THRESH_BINARY | cv.THRESH_OTSU)[1]
    # 计算每一组的轮廓,同上,计算外部轮廓及位置信息
    digitCnt, hierarchy = cv.findContours(group.copy(), cv.RETR_EXTERNAL,
                                          cv.CHAIN_APPROX_SIMPLE)
    digitCnt = myutils.sort_contours(digitCnt,
                                     method="left-to-right")[0]
    # 计算每一组中的每一个数值
    for c in digitCnt:
        # 找到当前数值的轮廓,resize成合适的的大小
        (x, y, w, h) = cv.boundingRect(c)
        roi = group[y:y + h, x:x + w]
        roi = cv.resize(roi, (57, 88))
        # 计算匹配得分,计算每一个数字与模板中数字相匹配的得分
        scores = []
        # 在模板中计算每一个得分
        for (digit, digitROI) in digits.items():
            # 模板匹配
            result = cv.matchTemplate(roi, digitROI,
                                      cv.TM_CCOEFF)
            (_, score, _, _) = cv.minMaxLoc(result)
            scores.append(score)
        # 得到最合适的数字
        groupOutput.append(str(np.argmax(scores)))
        # 画出来
        cv.rectangle(image, (gX - 5, gY - 5),
                     (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
        cv.putText(image, "".join(groupOutput), (gX, gY - 15),
                   cv.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
        # 得到结果
        output.extend(groupOutput)
# 打印结果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv.imshow("Image", image)
cv.waitKey(0)
cv.destroyAllWindows()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值