results of enforcement :

Main ideas : The outer contour of the template image and the image to be detected is detected , And get their circumscribed rectangles , Make the outer rectangle of the template image resize() operation , The size of the circumscribed rectangle is consistent with that of the image to be detected , Then the template matching is made with the graph to be detected
preparation :
1, Convert to grayscale image
2, Convert to binary image , In order to do contour detection
3, According to the length and width ratio of the contour , Filter out some useless interference information on the bank card
4, The above steps only give a rough outline , Some morphological operations are needed , Then split the numbers , Get more accurate digital information
be careful : When looking for a template , You should find a font that is very close to the font as a template

(1) Template pretreatment process : Each number in the template is grayscale converted , Binarization , Contour search , Contour drawing ,resize() The size of the contour and the contour value of each number ( Ordered ) Stored in a dictionary type variable
formwork drawing :

Template drawing after preprocessing :

code snippet :

img=cv.imread("E:\OpenCVTests\Samples\sample/nine/template-matching-ocr\images\ocr_a_reference.png")
gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,ref=cv.threshold(gray,10,255,cv.THRESH_BINARY_INV)# This step , We should add the front one ret, Otherwise, it will report an error
refCnts,hierarchy=cv.findContours(ref.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
# We'll continue to use it later ref, Therefore, it is necessary to use ref.copy(), Otherwise, the original image will be changed ; The second parameter is the specified outer contour detection ; The third parameter is a method of contour approximation
cv.drawContours(img,refCnts,-1,(0,0,255),3)#-1 Indicates that all contours are drawn , When other values are specified , Select only one in the image to draw a single contour
refCnts=contours.sort_contours(refCnts,method="left-to-right")[0]# Returns the sorted outline
digits={}# Create a dictionary type ,i Is the outline index ,c It's the outline ---- Dictionary type : Each index number corresponds to an index value for(i,c)in
enumerate(refCnts):#i Is the outline index ,c Is the corresponding contour , The detected contours are sorted
(x,y,w,h)=cv.boundingRect(c)# Get the upper left coordinate point and the length of each circumscribed rectangle , width
roi=ref[y:y+h,x:x+w]# The size of the bounding rectangle for each number roi=cv.resize(roi,(57,88))# Reset the size of the bounding rectangle to the appropriate size
digits[i]=roi# Each number corresponds to a template

(2) Image preprocessing process to be detected : It mainly includes morphological operation to remove noise , Gray scale conversion , Binarization ,Sobel() Function gradient , Contour related operations ( Contour search , Outline drawing , External contour , The contour is filtered according to the aspect ratio , sort ) And then go through every number in each block
Original image to be detected :

Perform a top cap operation :

Perform once Sobel() seek X Gradient operation in direction : Find the bright area in the graph

Perform a close operation : Make the content on the image appear in blocks

Perform a binary operation : Filter out clutter

Close again : Fill in the small black blocks in the white blocks

Perform contour detection , Contour drawing :

Then the contour is filtered according to the length width ratio of the contour , Filter out the needed contour information , It is found that 4 Group useful contour information , And loop through each of the four sets of outlines , The method is the same as above .

Complete code :
import cv2 as cv from imutils import contours import matplotlib as plt import
numpy as np FIRST_NUMBER = { "3": "American Express", "4": "Visa", "5":
"MasterCard", "6": "Discover Card" } # Preprocess the template image
img=cv.imread("E:\OpenCVTests\Samples\sample/nine/template-matching-ocr\images\ocr_a_reference.png")
gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,ref=cv.threshold(gray,10,255,cv.THRESH_BINARY_INV)# This step , We should add the front one ret, Otherwise, it will report an error
refCnts,hierarchy=cv.findContours(ref.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
# We'll continue to use it later ref, Therefore, it is necessary to use ref.copy(), Otherwise, the original image will be changed ; The second parameter is the specified outer contour detection ; The third parameter is a method of contour approximation
cv.drawContours(img,refCnts,-1,(0,0,255),3)#-1 Indicates that all contours are drawn , When other values are specified , Select only one in the image to draw a single contour
refCnts=contours.sort_contours(refCnts,method="left-to-right")[0]# Returns the sorted outline
digits={}# Create a dictionary type ,i Is the outline index ,c It's the outline ---- Dictionary type : Each index number corresponds to an index value for(i,c)in
enumerate(refCnts):#i Is the outline index ,c Is the corresponding contour , The detected contours are sorted
(x,y,w,h)=cv.boundingRect(c)# Get the upper left coordinate point and the length of each circumscribed rectangle , width
roi=ref[y:y+h,x:x+w]# The size of the bounding rectangle for each number roi=cv.resize(roi,(57,88))# Reset the size of the bounding rectangle to the appropriate size
digits[i]=roi# Each number corresponds to a template # Preprocess the image to be detected
recKernel=cv.getStructuringElement(cv.MORPH_RECT,(10,3))# In order to ensure the accuracy of detection information , Need to remove the bank card page clutter letter
sqKernel=cv.getStructuringElement(cv.MORPH_RECT,(2,2))# Therefore, we need to do morphological operation on the image , So convolution kernel is set up here
image=cv.imread("E:\OpenCVTests\Samples\sample/nine/template-matching-ocr\images\credit_card_01.png")
image=cv.resize(image,(250,200)) gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
tophat=cv.morphologyEx(gray,cv.MORPH_TOPHAT,recKernel)# Select the appropriate core according to the size of the font ; Top cap operation to highlight bright areas
gradx=cv.Sobel(tophat,ddepth=cv.CV_32F,dx=1,dy=0,ksize=3)# Yes X Or right Y It needs to be set according to actual needs or at the same time , Image gradient
gradx=np.absolute(gradx)# Take absolute value (minVal,maxVal)=(np.min(gradx),np.max(gradx))# normalization
gradx=(255*((gradx-minVal)/(maxVal-minVal))) gradx=gradx.astype("uint8")
gradx=cv.morphologyEx(gradx,cv.MORPH_CLOSE,recKernel)# Perform the close operation , Make the content on the image appear in blocks
ret,thresh=cv.threshold(gradx,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)# The reason why the low threshold is set to 0, Because the latter method is selected OTSU Automatic threshold setting , Suitable for bimodal image operation
thresh=cv.morphologyEx(thresh,cv.MORPH_CLOSE,sqKernel)# This close operation is to fill in the incomplete small blocks in the binary image
Cnts,hierarchy=cv.findContours(thresh.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
cnts=Cnts curImage=image.copy()
cv.drawContours(curImage,cnts,-1,(0,0,255),3)# The outline here is not the outline of the original image , It's the outline of the image after some column operations
locs=[] for (i,c)in enumerate(cnts): (x,y,w,h)=cv.boundingRect(c)# Make the circumscribed rectangle of each profile
ar=w/float(h)# Select useful rectangles according to the aspect ratio of the circumscribed rectangle , And add it to the tuple 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])# Filtered outline output=[] for (i,(gx,gy,gw,gh))in
enumerate(locs):# Traverse every number in each block groupOutput=[]
group=gray[gy-5:gy+gh+5,gx-5:gx+gw+5]# Take the outline and the area around it cv.imshow("group",group)
group=cv.threshold(group,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)[1]# hinder [] To add , Otherwise, an error will be reported copy, Next, the contour of each block is detected , draw
digitCnts,hierarchy=cv.findContours(group.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)# every last group Then the contour is detected , draw
digitCnts=contours.sort_contours(digitCnts,method="left-to-right")[0] for c in
digitCnts:# Calculate each value in each group (x,y,w,h)=cv.boundingRect(c) roi=group[y:y+h,x:x+w]
roi=cv.resize(roi,(57,88))# The size should correspond to the size of the formwork , Get the area of each number
scores=[]# Create an empty list , Used to store detected numbers for (digit,digitROI)in
digits.items():# The dictionary type of numerical value is established in template preprocessing , One is the index , One is the value
result=cv.matchTemplate(roi,digitROI,cv.TM_CCOEFF)# matching , Returns the value with the highest matching degree
(_,score,_,_)=cv.minMaxLoc(result)# do 10 Sub matching , Take the maximum value ( be careful : The maximum or minimum value depends on the template matching method selected )
scores.append(score) groupOutput.append(str(np.argmax(scores)))
cv.rectangle(image,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)# Rectangle of the first group
cv.putText(image,"".join(groupOutput),(gx,gy-15),cv.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)
output.extend(groupOutput) print("Credit Card Type:
{}".format(FIRST_NUMBER[output[0]])) print("Credit Card #:
{}".format("".join(output))) cv.imshow("Image",image) cv.waitKey(0)
cv.destroyAllWindows()

Technology
©2019-2020 Toolsou All rights reserved,
What are the protection measures for website security ? Talking about uni-app Page value transfer problem Remember once EventBus Project issues caused by memory leaks I've been drinking soft water for three years ? What is the use of soft water and water softener Time conversion front desk will 2020-07-17T03:07:02.000+0000 Into 2020-07-17 11:07:02 Chuan Shen Count the number of letters (java Language implementation ) Time format 2020-01-13T16:00:00.000Z Medium T and Z What do they mean , How to deal with it msf Generate Trojan horse attack android mobile phone The world's first free open source ERP Odoo Ubuntu The best development environment What's the difference in server prices ?