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,
( Super detail )Eclipse Using tutorials —— use Eclipse Create first HelloWorld! Database operation 5 code implementation mysql Addition, deletion, modification and query of database What can MCU do , Do you have any interesting works made by MCU or open source hardware Go to the interview after reading this , Steady over ~~ Single linked list of primary data structure (C Language implementation )SQL Comprehensive questions Employee unit comprehensive questions Python Implementation of Hanoi Tower code VHDL——JK trigger It's over , Starting salary 30k