信用卡识别(1)-预处理


实现目标:将信用卡图片上的卡号分组显示出来,显示每组分别是什么数字
如何匹配:模板匹配,通过每个数字来匹配

一、综述

在本博客中我们识别和生成我们日常之中信用卡数字的预选框,而后的博客中我将优化此博客,实现完整的手写数字的识别



二、流程

基本流程就是先处理我们的模板文件,然后在处理我们图像文件,然后把数字拆分出来进行模板匹配,然后把匹配到的数字进行输出,但是我这篇博客知识进行了我们输入图像的预选框勾画和原始模板图像数据的处理,而在接下来的过程中,我将来优化我的代码,多谢支持。



三、基本步骤


1.导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np
from cognize_creditcard import myutils
from imutils import contours
import argparse

2.设置参数

这里的参数是指的是信用卡的模板和你的信用卡的照片

ap = argparse.ArgumentParser()
ap.add_argument("-i","--image",required=True,
                help="path to input image")
ap.add_argument("-t","--template",required=True,
                help="path to template OCR-A image")
args = vars(ap.parse_args())

初始的模板
初始的图像


3.指定信用卡的类型

因为你的信用卡肯定不是只有一种类型的,所以你要根距信用卡的类型来选择你合适的类型。

FIRST_NUMBER = {
    "3": "American Express",
    "4": "Visa",
    "5": "MasterCard",
    "6": "Discover Card"
}

4.定义一个函数来展示你的照片

这里的函数是用来展示图像的

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

5.导入图像并转换为灰度

这里导入一张模板的图像进来,并进行输出

ref = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show('ref',ref)
img = cv2.imread(args['template'])
cv_show('img',img)

灰度的图像


6.进行二值操作并计算轮廓

在这里对我们的模板进行二值操作,但是因为他是黑白构成的所以我们的模板的变化并不是很大,然后我们勾画出我们每个图像的外轮廓,并进行模板数字的排序

ref = cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
ref_,refcnts,hierachy = cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refcnts,-1,(0,0,255),3)  # 只要轮廓,-1表示画出所有的轮廓,
cv_show('img',img)
print(np.array(refcnts).shape)
refcnts = myutils.sort_contours(refcnts,method='left-to-right')[0]  # 排序从左到右,从上到下

外轮廓包裹的图像

7.定义一个容器,装所有轮廓的索引和图像

定义一个容器来存放我们拆分了之后的模板的单个数字,这就是我们接下来来进行模板匹配的数字,我们现在将他们存放在对应的键值对中

digits = {}
# 遍历每个轮廓
for (i,c) in enumerate(refcnts): # c是每个轮廓,i是轮廓的索引
    # 计算外接矩形并且resize成合适大小
    (x,y,w,h) = cv2.boundingRect(c)
    roi = ref[y:y+h,x:x+w]
    roi = cv2.resize(roi,(57,88))

    # 每一个数字对应每一个模块
    digits[i] = roi



8.初始化卷积核
rectkernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqkernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))



9.输入我们的信用卡图像并进行预处理

预处理就是对数据进行灰度转换,以方便后面的预选框处理,并改变大小

image = cv2.imread(args["image"])
image = myutils.resize(image,width=300)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show('gray',gray)

进行了灰度转换后的图像



10.进行过滤,礼帽操作,突出更明亮的区域

突出更明亮的区域,以便后面的读取轮廓。

tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectkernel)
cv_show("tophat",tophat)
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F,dx=1, dy=0,
                  ksize=-1)   # -1 相当于3*3

gradX = np.absolute(gradX)
(minVAl, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255*((gradX - minVAl) / (maxVal -minVAl)))
gradX = gradX.astype('uint8')

print(np.array(gradX).shape)
cv_show('gradX',gradX)

顶帽操作



在这里插入图片描述



11.进行封闭操作

封闭操作就是先对图像进行膨胀,然后在进行腐蚀,在这个以后我们就可以将图像联系在一起

gradX = cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectkernel)
cv_show('gradx',gradX)

# THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,
                       cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('thresh',thresh)

# 再来一个闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqkernel)   # 再来一个闭操作
cv_show('thresh',thresh)

封闭操作加闭操作



12.计算轮廓,并画出我们的轮廓

通过他的矩形框我们来勾画出我们要的轮廓位置,然后我们将他的位置应用在原始图像的位置,这样我们就得到了我们数据的图像对应的位置,以方便后面的数字匹配,我将在后面进行更新。

# 计算轮廓
thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                                                  cv2.CHAIN_APPROX_SIMPLE)
# 画轮廓
cnts = threshCnts
cur_img = image.copy()
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
cv_show('img', cur_img)

有了轮廓的原始图像



四、实现代码

'''
实现目标:将信用卡图片上的卡号分组显示出来,显示每组分别是什么数字
如何匹配:模板匹配,通过每个数字来匹配
'''

# 导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np
from cognize_creditcard import myutils
from imutils import contours
import argparse


# 设置参数
ap = argparse.ArgumentParser()
ap.add_argument("-i","--image",required=True,
                help="path to input image")
ap.add_argument("-t","--template",required=True,
                help="path to template OCR-A image")
args = vars(ap.parse_args())

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

# show image to user
def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# input a origion image
img = cv2.imread(args['template'])
cv_show('img',img)

# 转换为灰度图
ref = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show('ref',ref)

# 二值操作,转换为二值图像,一般检测都是这个
ref = cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)

# 计算轮廓
# cv2.finContours() 函数接受的参数为二值图,即黑白的(不是灰度图像),cv2.CHATN_SIMPLE只保留终点坐标
# 返回的list中每个元素图像的一个轮廓
ref_,refcnts,hierachy = cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(img,refcnts,-1,(0,0,255),3)  # 只要轮廓,-1表示画出所有的轮廓,
cv_show('img',img)
print(np.array(refcnts).shape)
refcnts = myutils.sort_contours(refcnts,method='left-to-right')[0]  # 排序从左到右,从上到下
digits = {}

# 遍历每个轮廓
for (i,c) in enumerate(refcnts): # c是每个轮廓,i是轮廓的索引
    # 计算外接矩形并且resize成合适大小
    (x,y,w,h) = cv2.boundingRect(c)
    roi = ref[y:y+h,x:x+w]
    roi = cv2.resize(roi,(57,88))

    # 每一个数字对应每一个模块
    digits[i] = roi

# 初始化卷积核
rectkernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqkernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

# 读取输入图像,预处理
image = cv2.imread(args["image"])
cv_show("image",image)
image = myutils.resize(image,width=300)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show('gray',gray)

# 进行过滤操作
# 礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectkernel)
cv_show("tophat",tophat)
#
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F,dx=1, dy=0,
                  ksize=-1)   # -1 相当于3*3

gradX = np.absolute(gradX)
(minVAl, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255*((gradX - minVAl) / (maxVal -minVAl)))
gradX = gradX.astype('uint8')

print(np.array(gradX).shape)
cv_show('gradX',gradX)

# 进行封闭操作(先膨胀,在腐蚀)将数字连在一起。
gradX = cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectkernel)
cv_show('gradx',gradX)

# THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,
                       cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('thresh',thresh)

# 再来一个闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqkernel)   # 再来一个闭操作
cv_show('thresh',thresh)

# 计算轮廓
thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                                                  cv2.CHAIN_APPROX_SIMPLE)
# 画轮廓
cnts = threshCnts
cur_img = image.copy()
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
cv_show('img', cur_img)



五、需要的数据

模块:

链接:https://pan.baidu.com/s/1_fOszahHuVesF4uIdM0OFw
提取码:p0e0



结尾

这是一篇学习笔记,希望有错误联系博主。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
from imutils import contours import numpy as np import argparse import cv2 as cv import myutils def cv_show(name,img): cv.imshow(name,img) cv.waitKey(0) cv.destroyAllWindows() # 先处理template tempalte_img = cv.imread("E:/opencv/picture/ocr_a_reference.png") tempalte_gray = cv.cvtColor(tempalte_img, cv.COLOR_BGR2GRAY) tempalte_thres = cv.threshold(tempalte_gray, 0, 255, cv.THRESH_OTSU | cv.THRESH_BINARY_INV)[1] temp_a, tempalte_contours, temp_b = cv.findContours(tempalte_thres.copy (), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) cv.drawContours(tempalte_img, tempalte_contours, -1, (0, 255, 0), 2) tempalte_contours = contours.sort_contours(tempalte_contours, method="left-to-right")[0] digits = {} # 构建一个字典 for (i, c) in enumerate(tempalte_contours): (x, y, w, h) = cv.boundingRect(c) tempalte_roi = tempalte_thres[y:y + h, x:x + w] #之前一直检测不出正确答案,原因是这里的roi应该是tempalte_thres一部分 #而不是template_gray的一部分! tempalte_roi = cv.resize(tempalte_roi, (57, 88)) digits[i] = tempalte_roi cv_show('template_single',tempalte_roi) #cv_show('template_single',tempalte_roi) #对银行卡进行处理,之所以要做成数字长条,是想通过长条的尺寸比例大小来将自己想要的数字给抠出来。 rectkernel = cv.getStructuringElement(cv.MORPH_RECT,(9,3)) squrkernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5)) image = cv.imread("E:/opencv/picture/credit_card_02.png") image = myutils.resize(image, width=300) image_gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) image_tophat= cv.morphologyEx(image_gray,cv.MORPH_TOPHAT,rectkernel) image_close = cv.morphologyEx(image_tophat,cv.MORPH_CLOSE,rectkernel) cv.imshow("image_tophat",image_tophat) cv.imshow('image_close',image_close) image_thres= cv.threshold(image_close,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)[1] image_contours= cv.findContours(image_thres.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[1] locs = [] for(n,con) in enumerate(image_contours): (gx,
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值