信用卡数字的识别
项目逻辑:
我认为一个合格的项目组织者或者执行者需要从项目的整体架构掌握本身,首先对该项目的逻辑做一个整体的介绍:
一、项目需求:
1、信用卡数字的模板,用于匹配其他信用卡(并且已知)
2、各种信用卡,用于测试算法的准确性
二、项目流程
①
1)读入图像、灰度化、二值化进行数据预处理
2)画出处理的轮廓
3)对各个轮廓进行按照left-right排序
4)排序好之后进行保存
②
5)待处理的图像数据,灰度化
6)数据预处理:a)首先对轮廓进行顶帽操作,过滤掉不必要的噪声
b)完成形态学的闭操作,使得轮廓粘合在一起,方便找出需要的轮廓的范围,实现归一化、二值化、如果效果不好在进行一次形态学闭操作
7)以上操作可以分出四个区域,对四个区域的gray_image进行轮廓遍历,再进行轮廓细分(这个地方需要大家好好理解)。
8)打分,进行模板匹配打分。是在大的for循环中,执行小循环,形成4*4的scores矩阵,最后得出结果!
三、项目过程
1、对模板进行数据预处理(我没有使用命令行参数,这个需要的各位可以使用,下面对argpaser模块进行解释)
很多人查资料关于argparse模块的用法,网上众说纷纭,对于如果参数很多,比较复杂,并且类型不统一,那么argparse可以很好的解决这些问题,下面一个实例解释:
# 1、
import argparse
# description参数可以用于描述脚本的参数作用,默认为空 # 可以不写description
# 调用命令行参数,求长方形的面积
parser=argparse.ArgumentParser(description="The square of rectangle") # 声明一个对象
parser.add_argument('-w','--width',type=int,required=True,help='Use width')
parser.add_argument('-l','--length',type=int,required=True,help='use length')
# --width 是这个属性变量 -w 是选择性参数,顾名思义,可以在赋值的时候使用-w代替,
# required 是对非空的时候进行提示而不是直接运行出现逻辑错误,help就是咱们普通的理解
args=parser.parse_args() # 解释创建的对象
square = (args.width) * (args.length) # 注意调用的方式
print(square)
```python
我使用的是pycharm,大家在使用命令行参数的时候需要配置,菜单栏->run->edit configure...进行配置即可,有问题大家共同探讨
2、数据预处理 在进行数据预处理的过程,需要将模板的各个数据轮廓,
即cv2.findContours()命令,下面对这个函数进行解析
# 读入模板图像
img = cv2.imread('images/ocr_a_reference.png')
# cv_show('img',img)
# 灰度化
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# cv_show('img_gray',img_gray)
# 二值化
img_threshold = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV)[1] # [1]这个函数返回两个值 第二值比较有用 cv2.THRESH_BINARY_INV是取反操作,因为检测轮廓的时候目标是白色区域,故将原先二值化按照取反
#
# cv_show('img_threshold',img_threshold)
对函数cv2.findContours()函数,需要注意OpenCV4系列与之前的版本有所区别,之前这个函数是返回3个值,从4版本开始返回两个值:contour,binary ,其中c…为轮廓,b…为维度
3、
contour_s,binary = cv2.findContours(img_threshold.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # 在外边缘进行画框
# 1)注意需要将灰度图像拷贝一下,否则将在原图进行修改
# 2)需要将图像处理为灰度图才能进行二值化(基础知识)
cv2.drawContours(img,contour_s,-1,(0,0,255),3)
cv_show('img_draw',img) # -1 代表画出所有轮廓
4、介绍对轮廓排序算法
from imutils import contours # 你可以应用contours.sort_contours对轮廓进行排序,按照left-to-right的顺序,也可以使用方法myutils.sorted_contours自己定义的方法
# 注明:一下方法可以直接使用cv2.方法,这个方法作为参考,都可以使用!
import cv2
# 排序算法
def sorted_contours(cnt,method = 'left-to-right'):
reverse = False
i = 0
if method == 'right-to-left' or method == 'bottom-to-top' :
reverse = True # 指定排序顺序
if method == 'bottom-to-top' or method == 'top-to-bottom':
i = 1 # 指定按照元组中那个元素进行操作
boundingBoxs = [cv2.boundingRect(c) for c in cnt]
(cnt,boundingBoxs) = zip(*sorted(zip(cnt,boundingBoxs),key=lambda b:b[1][i],reverse = reverse))
return cnt,boundingBoxs
def resize(image,width=None,height=None,inter=cv2.INTER_AREA):
dim = None
(h,w) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
r = height / float(h)
dim = (int(w * r), height)
else:
r = width / float(w)
dim = (width,int(h * r))
resized = cv2.resize(image,dim,interpolation=inter)
return resized
5、对所有模板进行保存
digitals = {
}
contour_s = myutils.sorted_contours(contour_s,method='left-to-right')[0]
for i,c in enumerate(contour_s):
x,y,w,h = cv2.boundingRect(c)
roi = img_gray[y:y