当前位置:网站首页>The practice of OpenCV -- bank card number recognition
The practice of OpenCV -- bank card number recognition
2022-07-26 10:11:00 【SingleDog_ seven】
First, let's introduce the library we need and the image display we define ( convenient ):
import cv2
import numpy as np
import imutils
from imutils import contours
# Display images
def cv_show(img,name="image"):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyWindow(name)
Secondly, let's introduce the template of bank card numbers and carry out preprocessing :

template=cv2.imread('TT.jpg')
# cv_show(template)
# Convert to grayscale
ref_template=cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
# cv_show(ref_template)
# Convert to binary graph
ref_template=cv2.threshold(ref_template,10,255,cv2.THRESH_BINARY_INV)[1]
# cv_show(ref_template)
# Contour detection
##findContours Only accept binary graphs RETR_EXTERNAL Only the outer contour is detected CHAIN_APPROX_SIMPLE Keep only the end coordinates
BIT,refCnts,hierarchy=cv2.findContours(ref_template.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(template,refCnts,-1,(0,0,255),3)
# cv_show(template)
# print(np.array(refCnts).shape)
# Sort outline
refCnts=contours.sort_contours(refCnts,method="left-to-right")[0]
# print(refCnts)
digits={}
for (i,c) in enumerate(refCnts):
# Calculate the circumscribed rectangle
(x,y,w,h)=cv2.boundingRect(c)
roi=ref_template[y:y+h,x:x+w]
#resize To the right size
roi=cv2.resize(roi,(57,88))
# cv_show(roi)
# Each number corresponds to a template
digits[i]=roi
Next, introduce and process the bank card we need to identify :

# Initialize convolution kernel
rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
# Read input image
image=cv2.imread('T1.jpg')
# cv_show(image)
image=imutils.resize(image,width=300)
image_gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# cv_show(image_gray)
#tophat Top hat operation , Highlight bright areas
image_tophat=cv2.morphologyEx(image_gray,cv2.MORPH_TOPHAT,rectKernel)
# cv_show(image_tophat)
# Calculate the gradient Make the outline clearer
gradX=cv2.Sobel(image_tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)#ksize=-1 To express with 3*3 And nucleus
gradX=np.absolute(gradX)
(minVal,maxVal)=(np.min(gradX),np.max(gradX))
gradX=(255*(gradX-minVal)/(maxVal-minVal))
gradX=gradX.astype("uint8")
# print(np.array(gradX).shape)
# cv_show(gradX)
# Close your operations ( Expand first and then corrode ) Put the numbers together
gradX=cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)
# cv_show(gradX)
# Two valued
image_thresh=cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
# cv_show(image_thresh)
# Close again after binarization
image_thresh=cv2.morphologyEx(image_thresh,cv2.MORPH_CLOSE,sqKernel)
# cv_show(image_thresh)
# Calculate the contour
BITT,threshCnts,hierarchy=cv2.findContours(image_thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image.copy(),threshCnts,-1,(0,0,255),1)
# cv_show(image)
Finally, let's match the bank card template and the digital template :
locs=[]
for (i,c) in enumerate(threshCnts):
(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])
output=[]
for (i,(gx,gy,gw,gh)) in enumerate(locs):# gx,gy,gw,gh representative 4000 This area
groupOutput=[]
# Extract each set of numbers ( One group includes 4 A digital )
group=image_gray[gy-5:gy+gh+5,gx-5:gx+gw+5]
# cv_show(group)
group=cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
# cv_show(group)
B,digitsCnts,A=cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
digitsCnts=imutils.contours.sort_contours(digitsCnts,method="left-to-right")[0]
# print(digitsCnts)
for c in digitsCnts: # Go through every number Such as 4000 Traverse in turn 4、0、0、0
(x,y,w,h)=cv2.boundingRect(c)
# print((x,y,w,h))
roi=group[y:y+h,x:x+w]
# Set the matching image to the consistent size of the template image
roi=cv2.resize(roi,(57,88))
# cv_show(roi)
# Calculate the match score
scores=[]
for (digit,digitROI) in digits.items():
# Template matching
result=cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF)
(_,score,_,_)=cv2.minMaxLoc(result)
scores.append(score)
groupOutput.append(str(np.argmax(scores)))
cv2.rectangle(image,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)
cv2.putText(image,"".join(groupOutput),(gx,gy-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)
output.extend(groupOutput)
cv_show(image)
print("".join(output))

The result shown at last .
Full code :
import cv2
import numpy as np
import imutils
from imutils import contours
# Display images
def cv_show(img,name="image"):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyWindow(name)
template=cv2.imread('TT.jpg')
# cv_show(template)
# Convert to grayscale
ref_template=cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
# cv_show(ref_template)
# Convert to binary graph
ref_template=cv2.threshold(ref_template,10,255,cv2.THRESH_BINARY_INV)[1]
# cv_show(ref_template)
# Contour detection
##findContours Only accept binary graphs RETR_EXTERNAL Only the outer contour is detected CHAIN_APPROX_SIMPLE Keep only the end coordinates
BIT,refCnts,hierarchy=cv2.findContours(ref_template.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(template,refCnts,-1,(0,0,255),3)
# cv_show(template)
# print(np.array(refCnts).shape)
# Sort outline
refCnts=contours.sort_contours(refCnts,method="left-to-right")[0]
# print(refCnts)
digits={}
for (i,c) in enumerate(refCnts):
# Calculate the circumscribed rectangle
(x,y,w,h)=cv2.boundingRect(c)
roi=ref_template[y:y+h,x:x+w]
#resize To the right size
roi=cv2.resize(roi,(57,88))
# cv_show(roi)
# Each number corresponds to a template
digits[i]=roi
# Initialize convolution kernel
rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
# Read input image
image=cv2.imread('T1.jpg')
# cv_show(image)
image=imutils.resize(image,width=300)
image_gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# cv_show(image_gray)
#tophat Top hat operation , Highlight bright areas
image_tophat=cv2.morphologyEx(image_gray,cv2.MORPH_TOPHAT,rectKernel)
# cv_show(image_tophat)
# Calculate the gradient Make the outline clearer
gradX=cv2.Sobel(image_tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)#ksize=-1 To express with 3*3 And nucleus
gradX=np.absolute(gradX)
(minVal,maxVal)=(np.min(gradX),np.max(gradX))
gradX=(255*(gradX-minVal)/(maxVal-minVal))
gradX=gradX.astype("uint8")
# print(np.array(gradX).shape)
# cv_show(gradX)
# Close your operations ( Expand first and then corrode ) Put the numbers together
gradX=cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)
# cv_show(gradX)
# Two valued
image_thresh=cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
# cv_show(image_thresh)
# Close again after binarization
image_thresh=cv2.morphologyEx(image_thresh,cv2.MORPH_CLOSE,sqKernel)
# cv_show(image_thresh)
# Calculate the contour
BITT,threshCnts,hierarchy=cv2.findContours(image_thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image.copy(),threshCnts,-1,(0,0,255),1)
# cv_show(image)
locs=[]
for (i,c) in enumerate(threshCnts):
(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])
output=[]
for (i,(gx,gy,gw,gh)) in enumerate(locs):# gx,gy,gw,gh representative 4000 This area
groupOutput=[]
# Extract each set of numbers ( One group includes 4 A digital )
group=image_gray[gy-5:gy+gh+5,gx-5:gx+gw+5]
# cv_show(group)
group=cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
# cv_show(group)
B,digitsCnts,A=cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
digitsCnts=imutils.contours.sort_contours(digitsCnts,method="left-to-right")[0]
# print(digitsCnts)
for c in digitsCnts: # Go through every number Such as 4000 Traverse in turn 4、0、0、0
(x,y,w,h)=cv2.boundingRect(c)
# print((x,y,w,h))
roi=group[y:y+h,x:x+w]
# Set the matching image to the consistent size of the template image
roi=cv2.resize(roi,(57,88))
# cv_show(roi)
# Calculate the match score
scores=[]
for (digit,digitROI) in digits.items():
# Template matching
result=cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF)
(_,score,_,_)=cv2.minMaxLoc(result)
scores.append(score)
groupOutput.append(str(np.argmax(scores)))
cv2.rectangle(image,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)
cv2.putText(image,"".join(groupOutput),(gx,gy-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)
output.extend(groupOutput)
cv_show(image)
print("".join(output))
Different versions findContours Functions may be used in different ways , Some higher versions require only two return values .
All the above are used in the past opencv What I learned , There may also be something you haven't learned ,

边栏推荐
- MySQL 5.7.25 source code installation record
- Okaleido生态核心权益OKA,尽在聚变Mining模式
- IEEE conference upload font problem
- Like, "new programmer" e-book is free for a limited time!
- Session based recommendations with recurrent neural networks
- Tableviewcell highly adaptive
- Xiaobai makes a wave of deep copy and shallow copy
- Apple dominates, Samsung revives, and domestic mobile phones fail in the high-end market
- Basic usage of protobuf
- 解释一下自动装箱和自动拆箱?
猜你喜欢

服务器内存故障预测居然可以这样做!

SSG framework Gatsby accesses the database and displays it on the page

数通基础-Telnet远程管理设备

Production of a-modal drag function in antui

Matlab Simulink realizes fuzzy PID control of time-delay temperature control system of central air conditioning

B站这个视频我是跪着看完的

Alibaba cloud technology expert haochendong: cloud observability - problem discovery and positioning practice
![Sqoop [environment setup 01] CentOS Linux release 7.5 installation configuration sqoop-1.4.7 resolve warnings and verify (attach sqoop 1 + sqoop 2 Latest installation package +mysql driver package res](/img/8e/265af6b20f79b21c3eadcd70cfbdf7.png)
Sqoop [environment setup 01] CentOS Linux release 7.5 installation configuration sqoop-1.4.7 resolve warnings and verify (attach sqoop 1 + sqoop 2 Latest installation package +mysql driver package res

Common errors when starting projects in uniapp ---appid

Leetcode 504. Hex number
随机推荐
Okaleido ecological core equity Oka, all in fusion mining mode
2022 zhongkepan cloud - server internal information acquisition and analysis flag
The problem of four columns of Hanoi Tower
万字详解“用知识图谱驱动企业业绩增长”
新增市场竞争激烈,中国移动被迫推出限制性超低价5G套餐
Vectortilelayer replacement style
Transform between tree and array in JS (hide the children field if the child node of the tree is empty)
Interview shock 68: why does TCP need three handshakes?
Wechat applet learning notes 1
MySQL function
Introduction to latex, EPS picture bounding box
新建福厦铁路全线贯通 这将给福建沿海带来什么?
Sqoop【环境搭建 01】CentOS Linux release 7.5 安装配置 sqoop-1.4.7 解决警告并验证(附Sqoop1+Sqoop2最新版安装包+MySQL驱动包资源)
JS judge the data types object.prototype.tostring.call and typeof
SSG framework Gatsby accesses the database and displays it on the page
网易云UI模仿--&gt;侧边栏
Network related journals and conferences in CS
Xiaobai makes a wave of deep copy and shallow copy
Under win10 64 bit, matlab fails to configure notebook
Azkaban [basic knowledge 01] core concepts + features +web interface + Architecture +job type (you can get started with Azkaban workflow scheduling system in one article)