文章目录
实现目标:将信用卡图片上的卡号分组显示出来,显示每组分别是什么数字 如何匹配:模板匹配,通过每个数字来匹配
一、综述
在本博客中我们识别和生成我们日常之中信用卡数字的预选框,而后的博客中我将优化此博客,实现完整的手写数字的识别
二、流程
基本流程就是先处理我们的模板文件,然后在处理我们图像文件,然后把数字拆分出来进行模板匹配,然后把匹配到的数字进行输出,但是我这篇博客知识进行了我们输入图像的预选框勾画和原始模板图像数据的处理,而在接下来的过程中,我将来优化我的代码,多谢支持。
三、基本步骤
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
结尾
这是一篇学习笔记,希望有错误联系博主。