代码
import numpy as np
import cv2
def cv_display(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def read_template(template_file):
template = cv2.imread(template_file)
gray = cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
ref = cv2.threshold(gray,10,255,cv2.THRESH_BINARY_INV)[1]
#cv_display("ref",ref)
return template,ref
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
def find_contours(img,ref):
ref_copy = ref.copy()
contour,hierarchy= cv2.findContours(ref_copy,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,contour,-1,(0,0,255),3)
#cv_display("img",img)
#print (np.array(contour).shape)
contour = sort_contours(contour,method="left-to-right")[0]
digits={}
for i,c in enumerate(contour):
(x,y,w,h) = cv2.boundingRect(c)
roi = ref[y:y+h,x:x+w]
roi=cv2.resize(roi,(57,88))
digits[i]=roi
return digits
def discern_img(img_file,digits):
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
img = cv2.imread(img_file)
h,w = img.shape[0:2]
width=300
height = int(h*(width/w))
img = cv2.resize(img,(width,height),interpolation = cv2.INTER_AREA)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
#cv_display("tophat",tophat)
gradX=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)
gradX = np.absolute(gradX)
(minVal,maxVal)=(np.min(gradX),np.max(gradX))
gradX = (255*((gradX-minVal)/(maxVal-minVal)))
gradX = gradX.astype("uint8")
gradX = cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)
#cv_display("gradX",gradX)
thresh = cv2.threshold(gradX,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
thresh = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel)
#cv_display("thresh",thresh)
contour,hierarchy= cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cur_img = img.copy()
cv2.drawContours(cur_img,contour,-1,(0,0,255),3)
cv_display("cur_img",cur_img)
locs = []
for i,c in enumerate(contour):
(x,y,w,h) = cv2.boundingRect(c)
ar = w/h
if ar>2.5 and ar<4.0:
if (w>40 and 2<55) and(h>10 and h<20):
locs.append((x,y,w,h))
locs =sorted(locs,key=lambda x:x[0])
output =[]
for (i,(gx,gy,gw,gh)) in enumerate(locs):
groupOutput =""
group = gray[gy-5:gy+gh+5,gx-5:gx+gw+5]
#cv_display("group",group)
group_area = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#cv_display("group_area",group_area)
contour_new,hierarchy= cv2.findContours(group_area.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
digitscnts = sort_contours(contour_new,method="left-to-right")[0]
scores =[]
for c in digitscnts:
(x,y,w,h) = cv2.boundingRect(c)
roi = group[y:y+h,x:x+w]
roi=cv2.resize(roi,(57,88))
#cv_display("roi",roi)
scores=[]
for digit,digitROI in digits.items():
result = cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF)
_,score,_,_=cv2.minMaxLoc(result)
scores.append(score)
groupOutput+=(str(np.argmax(scores)))
output.append(groupOutput)
cv2.rectangle(img, (gx - 5, gy - 5),(gx + gw + 5, gy + gh + 5), (0, 0, 255), 1)
cv2.putText(img,groupOutput, (gx, gy-15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
cv_display("img",img)
cv2.imwrite("result.png",img)
print ("finally result={}".format(output))
def main():
img_file= "credit_card_01.png"
template_file="ocr_a_reference.png"
img,ref = read_template(template_file)
digits=find_contours(img,ref)
img= discern_img(img_file,digits)
if __name__ == "__main__":
main()
素材
对比
import cv2 as cv
import numpy as np
def display_img(img):
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()
def double_img(file1,file2):
img1 = cv.imread(file1)
img2 = cv.imread(file2)
res = np.hstack((img1,img2))
display_img(res)
double_img("credit_card_01_.png","result.png")
参考:https://www.bilibili.com/video/BV1VC4y1h7wq?p=8