对于模板图片
1:先进行灰度处理,在进行二值化处理,
2:获取轮廓
3:得到轮廓中的数字
4:对轮廓中的数字进行排序
对于要识别的图片
1:先进行灰度处理,在进行二值化处理,
2:先膨胀在腐蚀,得到卡号数字矩形轮廓
3:将得到的轮廓进行裁剪原图,拿到卡号图片
4:卡号图片在与模板图片对比
import cv2
import numpy as np
import TemplatePNG as tp
import matplotlib.pyplot as plt
#在此之前 ,需要对图片进行归一化处理,即所有识别的大小应该保持一样
#此方法没考虑照片的方向性质
def cv_show(img):
cv2.imshow('name',img)
cv2.waitKey()
cv2.destroyAllWindows()
#灰度图
img=cv2.imread('images/credit_card_02.png')
ref = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值图像
ref = cv2.threshold(ref, 127, 255, cv2.THRESH_BINARY_INV)[1]
cv_show(ref)
kernel=np.ones((3,3),np.uint8)
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
#需要得到轮廓信息将数字连在一起,梯度运算效果比较好=膨胀-腐蚀
closing=cv2.morphologyEx(ref,cv2.MORPH_GRADIENT,rectKernel)
closing=cv2.morphologyEx(closing,cv2.MORPH_GRADIENT,rectKernel)
#填充图片区域,先膨胀,在腐蚀
closing=cv2.morphologyEx(closing,cv2.MORPH_CLOSE,rectKernel)
cv_show(closing)
#获取原图像矩形轮廓,必须传入二值化后的图
binary, contours, hierarchy =cv2.findContours(closing, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res = cv2.drawContours(ref.copy(), contours, -1, (0, 0, 255), 2)
cv_show(res)
#过滤掉多余的矩形轮廓
locs=[]
for (a,b) in enumerate(contours):
(x,y,w,h) =cv2.boundingRect(b)
scale=w/float(h)
#获取坐标
if scale>=2.5 and scale<4.0 :
locs.append((x,y,w,h))
print("数据:",(x,y,w,h))
#观察数据,实际不能这么操作,将每条y,w,h相近的坐标取出来范围上下10左右
locs2=[]
for (x,y,w,h) in locs:
if h>=30 and h<=40:
locs2.append((x,y,w,h))
#按照x坐标进行排序
locs2.sort(key= lambda x:x[0],reverse=False)
#找到4个大的轮廓后,在到四个小的轮廓中找到小轮廓,并用矩形圈出来,在通过模板进行一个个匹配
print(locs2)
ResultList=[]
restmap=tp.getMap()
for (i,(gx,gy,gw,gh)) in enumerate(locs2):
#得到小图片
roi= ref[gy:gy + gh, gx:gx + gw]
#变成白色字体,与模板字体一样
roi = cv2.threshold(roi, 127, 255, cv2.THRESH_BINARY_INV)[1]
cv_show(roi)
#得到轮廓信息
resList=[]
a1, b1, c1 =cv2.findContours(roi, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for (a,b) in enumerate(b1):
(x,y,w,h) =cv2.boundingRect(b)
if y>0 and y<3 and h>=23 and h<=40:
resList.append((x,y,w,h))
#过滤掉不需要的轮廓
resList.sort(key=lambda x:x[0],reverse=False)
list2=[]
#从每个小4x4的图片找出矩形框
for (i,(x,y,w,h)) in enumerate(resList):
reg=roi[y:y+h,x:x+w]
reg = cv2.resize(reg, (57, 88))
#遍历模板通过使用cv2模板方法进行匹配,并保存分数 ,选择分数最高的一个
num=-1;
sou=-1;
for k,v in restmap.items():
result=cv2.matchTemplate(reg,v,cv2.TM_CCOEFF)
#值越大越相关
(_,souce,_,_)=cv2.minMaxLoc(result)
if souce>sou:
num=k
sou=souce
ResultList.append(num)
list2.append(num)
# 把数字画出来
cv2.putText(img, str(num), (gx+x, gy - 15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
cv2.rectangle(img, (gx , gy ),(gx + gw , gy + gh ), (0, 0, 255), 1)
cv_show(img)
print(ResultList)
TemplatePNG.py代码
import cv2
import numpy as np
def cv_show(img):
cv2.imshow('name',img)
cv2.waitKey()
cv2.destroyAllWindows()
map={}
def getMap():
if(len(map)==10):
return map
#处理模板图片
img=cv2.imread('images/ocr_a_reference.png')
ref = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值图像
ref = cv2.threshold(ref, 127, 255, cv2.THRESH_BINARY_INV)[1]
binary, contours, hierarchy=cv2.findContours(ref,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
locs=[]
#过滤掉不和条件的轮廓,并按照x大小进行排序
for (a,b) in enumerate(contours):
(x,y,w,h) =cv2.boundingRect(b)
#print(x,y,w,h)
if y>16 and y<24 and w>48 and w <59 and h>82 and h<90:
locs.append((x,y,w,h))
print(x,y,w,h)
#通过x坐标进行排序
locs.sort(key= lambda x:x[0],reverse=False)
#放到一个map中
for (i,(x,y,w,h)) in enumerate(locs):
#画出矩形框
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
#遍历得到模板内容
roi = ref[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
#将模板内容和数据放到集合中
map[i]=roi
#print(map)
return map
模板图片