python基于opencv的银行卡数字识别

python基于opencv实现银行卡数字的识别

import cv2 as cv
import numpy as np


def cv_show(title, image):
    cv.imshow(title, image)
    cv.waitKey(0)
    cv.destroyAllWindows()


# 读取图片
num_img = cv.imread('./images/0-1.png')
# 转灰度
num_img_gray = cv.cvtColor(num_img, cv.COLOR_BGR2GRAY)
# 预值处理
ret, thresh = cv.threshold(num_img_gray, 127, 255, cv.THRESH_BINARY_INV)
# 边缘检测
contours, hierarchy = cv.findContours(thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
MaxRect = []
for cts in contours:
    MaxRect.append(cv.boundingRect(cts))

cts, MaxRect = zip(*sorted(zip(contours, MaxRect), key=lambda x: x[1][0], reverse=False))
dect_roi = {}
for i, maxrect in enumerate(MaxRect):
    x, y, w, h = maxrect
    roi = thresh[y:(y + h), x:(x + w)]
    roi = cv.resize(roi, (57, 88))
    dect_roi[i] = roi

# 最佳阈值?
card_img = cv.imread('./images/card.png')
h, w = card_img.shape[:2]
r = 320 / w
card_img = cv.resize(card_img, (320, int(h * r)))
card_img_gray = cv.cvtColor(card_img, cv.COLOR_BGR2GRAY)
# 礼帽
kernel = cv.getStructuringElement(cv.MORPH_RECT, (9, 3))
top = cv.MORPH_TOPHAT
img_top = cv.morphologyEx(card_img_gray, top, kernel, iterations=3)
# 5.边缘检测
# 水平方向
sobel_x = cv.Sobel(img_top, ddepth=cv.CV_64F, dx=1, dy=0, ksize=5)
sobel_x = np.absolute(sobel_x)
(max_val, min_val) = (np.max(sobel_x), np.min(sobel_x))
sobel_x = ((sobel_x - min_val) / (max_val - min_val)) * 255
# 垂直方向
sobel_y = cv.Sobel(img_top, ddepth=cv.CV_64F, dx=0, dy=1, ksize=5)
sobel_y = np.absolute(sobel_y)
(max_val, min_val) = (np.max(sobel_y), np.min(sobel_y))
sobel_y = ((sobel_y - min_val) / (max_val - min_val)) * 255
sobel = (sobel_x + sobel_y).astype('uint8')
# 6.闭运算
img_close = cv.morphologyEx(sobel, cv.MORPH_CLOSE, kernel=kernel, iterations=2)
# 7.明亮(阈值)
thresh_index, thresh_img = cv.threshold(img_close, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# 7.2.膨胀
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
img_dilate = cv.morphologyEx(thresh_img, cv.MORPH_DILATE, kernel=kernel, iterations=2)
# cv_show('dilate', img_dilate)
# 8.指定特定区域[选择出来-->排序 4000一组]
img_copy = card_img.copy()
card_contours, card_cts = cv.findContours(img_dilate, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
MinBox_MaxRect = []
for cts in card_contours:
    x, y, w, h = cv.boundingRect(cts)
    if (55 < w < 70) and (15 < h < 30):

        MinBox_MaxRect.append(cv.boundingRect(cts))
Locs = sorted(MinBox_MaxRect, key=lambda x: x[0])
# 遍历每一个轮廓中的数字
output = []
for (i, (gX, gY, gW, gH)) in enumerate(Locs):
    groupOutput = []
    # 根据坐标提取每一个组
    group = card_img_gray[gY - 3:gY + gH + 3, gX - 3:gX + gW + 3]
    # # 预处理
    group = cv.threshold(group, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)[1]
    # # 计算每一组的轮廓
    digitCts, hierarchy = cv.findContours(group, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    group_rect = []
    for c in digitCts:
        group_rect.append(cv.boundingRect(c))
        group_rect = sorted(group_rect, key=lambda x: x[0])
    for r in group_rect:
        (x, y, w, h) = r
        roi = group[y:y + h, x:x + w]
        roi = cv.resize(roi, (57, 88))

        scores = []
        for (digit, digitROI) in dect_roi.items():
            # 模板匹配
            result = cv.matchTemplate(roi, digitROI, cv.TM_CCOEFF)
            (_, score, _, _) = cv.minMaxLoc(result)
            scores.append(score)
        groupOutput.append(str(np.argmax(scores)))

    output.append(groupOutput)
    cv.rectangle(img_copy, (gX - 3, gY - 3), (gX + gW + 3, gY + gH + 3), (0, 0, 255), 2)
    cv.putText(img_copy, "".join(groupOutput), (gX, gY - 15), cv.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
cv_show('copy', img_copy)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值