这个非常麻烦,麻烦到我真的不想做
但是我也没有办法的呢
好了开始这个图片数字识别
例如把下面的信用卡上的数字识别出来

因为这次的代码分段比较多,所以把重复操作的过程打包成函数提前运行了
import cv2
import numpy as np
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
def sort_contours(cnts,method = "left-to-right"):
reverse = False
i=0
if method == "right-to-left"or method == "bottom-to-top":
reverse = True
if method == "top-to-bottom"or method =="bottom-to-top":
i=1
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts,boundingBoxes) = zip(*sorted(zip(cnts,boundingBoxes),key =lambda b:b[1][i],reverse = reverse))
return cnts,boundingBoxes
- 上面的代码看着多其实也就俩功能,一个显示图片,另一个是排序检测出来的图片,并且框选出来
- 下面先对模板进行二值化处理
template = cv2.imread("ocr_a_reference.png")
cv_show("template",template)
template_gary = cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
ret,template_binary = cv2.threshold(template_gary,0,255,1)
cv_show("template_binary",template_binary)

- 使用上面的函数把图片框选出来之后一个一个切分出来,并进行排序赋值
cnts,h = cv2.findContours(template_binary,cv2.RETR_EXTERNAL,\
cv2.CHAIN_APPROX_SIMPLE)
template_rect =cv2.drawContours(template.copy(),cnts,-1,(0,0,255),2)
cv_show("template_rect",template_rect)
cnts = sort_contours(cnts)[0]
number = {}
for (i,cnt) in enumerate(cnts):
(x,y,w,h) = cv2.boundingRect(cnt)
roi =template_binary[y:y+h,x:x+w]
roi = cv2.resize(roi,(57,88))
number[i]= roi
cv_show("roi",roi)
- 接下来对原图进行处理,先二值化然后进行礼帽处理总之都是为了去除噪点
cardImg = cv2.imread("credit_card_01.png")
h,w = cardImg.shape[:2]
cardImg = cv2.resize(cardImg,(300,int(float(300/w)*h)))
cardImg_gary = cv2.cvtColor(cardImg,cv2.COLOR_BGR2GRAY)
cv_show("cardImg_gary",cardImg_gary)
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
cardImg_tophat = cv2.morphologyEx(cardImg_gary,cv2.MORPH_TOPHAT,rectKernel)
cv_show("cardImg_tophat",cardImg_tophat)
- 之后就是边缘检测,寻找出图片里所有图形的边缘
sobelx =cv2.Sobel(cardImg_tophat,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
(minX,manX) = (np.min(sobelx),np.max(sobelx))
sobelx =(255*((sobelx-minX)/(manX-minX)))
sobelx = sobelx.astype('uint8')
cv_show("sobelx",sobelx)
- 再使用函数腐蚀膨胀之后把大轮廓留下,小轮廓去除
cardImg_close = cv2.morphologyEx(sobelx,cv2.MORPH_CLOSE,rectKernel)
cardImg_binary =cv2.threshold(cardImg_close,0,255,cv2.THRESH_OTSU | cv2.THRESH_BINARY)[1]
cardImg_close = cv2.morphologyEx(cardImg_binary,cv2.MORPH_CLOSE,sqKernel)
cv_show("cardImg_close",cardImg_close)
- 然后就是找到所有的大轮廓把大轮廓框选出来
cnts,h = cv2.findContours(cardImg_close,cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cardImg_cnts =cv2.drawContours(cardImg.copy(),cnts,-1,(0,0,255),2)
cv_show("cardImg_cnts",cardImg_cnts)
locs =[]
for (i,c) in enumerate(cnts):
(x,y,w,h) = cv2.boundingRect(c)
ar = w/ float(h)
if ar>2.5 and ar< 4.0 :
if (w >40 and w<55) and(h >10 and h <20):
locs.append((x,y,w,h))
locs = sorted(locs, key = lambda x:x[0])
for (x,y,w,h) in locs:
cv2.rectangle(cardImg_cnts,(x,y),(x+w,y+h),(0,0,255),3)
cv_show("cardImg_cnts",cardImg_cnts)
- 最后就是和模板比对,并且把识别出的数字写在图片上
output = []
for (i,(x,y,w,h)) in enumerate(locs):
group_output = []
group = cardImg_gary[y-5:y + h +5,x-5:x + w + 5]
group = cv2.threshold(group,0,255,cv2.THRESH_OTSU|cv2.THRESH_BINARY)[1]
cv_show("group",group)
group_cnts,h= cv2.findContours(group,cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
group_cnts = sort_contours(group_cnts,method = "left-to-right")[0]
for cnt in group_cnts:
(nx,ny,nw,nh) = cv2.boundingRect(cnt)
roi =group[ny:ny+nh,nx:nx+nw]
roi = cv2.resize(roi,(57,88))
score = []
cv_show("roi",roi)
for (number_i,number_roi) in number.items():
result = cv2.matchTemplate(roi,number_roi,cv2.TM_CCOEFF)
score_ = cv2.minMaxLoc(result)[1]
score.append(score_)
group_output.append(str(np.argmax(score)))
cv2.putText(cardImg,"".join(group_output),(x,y-15),
cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)
output.append(group_output)
cv_show('cardImg',cardImg)
运行结果如下
版权声明:本文为qq_54546389原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。