当前位置:网站首页>opencv学习笔记四--银行卡号识别
opencv学习笔记四--银行卡号识别
2022-07-01 14:52:00 【Cloudy_to_sunny】
前期步骤
导入工具包
from imutils import contours
import numpy as np
import argparse
import cv2
import myutils
import matplotlib.pyplot as plt#Matplotlib是RGB
指定信用卡类型
# 指定信用卡类型(根据卡号第一位数字)
FIRST_NUMBER = {
"3": "American Express",
"4": "Visa",
"5": "MasterCard",
"6": "Discover Card"
}
定义绘图函数
# 绘图展示
def cv_show(name,img):
b,g,r = cv2.split(img)
img_rgb = cv2.merge((r,g,b))
plt.imshow(img_rgb)
plt.show()
def cv_show1(name,img):
plt.imshow(img)
plt.show()
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
读入数据
# 读取一个模板图像
img = cv2.imread("./ocr_a_reference.png")
cv_show('img',img)

# 灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show1('ref',ref)

# 二值图像
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show1('ref',ref)

模板处理
计算轮廓
#cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓
ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,0,255),3)
cv_show1('img',img)

print (np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {
}
(10,)
d:\Miniconda3\envs\learnCV\lib\site-packages\ipykernel_launcher.py:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
"""Entry point for launching an IPython kernel.
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):
# 计算外接矩形并且resize成合适大小
(x, y, w, h) = cv2.boundingRect(c)
roi = ref[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
# 每一个数字对应每一个模板
digits[i] = roi
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
卡片处理
#读取输入图像,预处理
image = cv2.imread("./images/credit_card_01.png")
cv_show('image',image)
image = myutils.resize(image, width=300)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show1('gray',gray)


#礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv_show1('tophat',tophat)
# 计算x方向图像梯度
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的
ksize=-1)

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_show1('gradX',gradX)
(189, 300)

#通过闭操作(先膨胀,再腐蚀)将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show1('gradX',gradX)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8AcGUyGC-1656380868739)(https://gitcode.net/weixin_41756645/csdnimage/-/raw/master/ocr_match_files/ocr_match_19_0.png)]
#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show1('thresh',thresh)

#再来一个闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show1('thresh',thresh)

# 计算轮廓
thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = threshCnts
cur_img = image.copy()
cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)
cv_show('img',cur_img)
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])
output = []
# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):
# initialize the list of group digits
groupOutput = []
# 根据坐标提取每一个组
group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
cv_show1('group',group)
# 预处理
group = cv2.threshold(group, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show1('group',group)
# 计算每一组的轮廓
group_,digitCnts,hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
digitCnts = contours.sort_contours(digitCnts,
method="left-to-right")[0]
# 计算每一组中的每一个数值
for c in digitCnts:
# 找到当前数值的轮廓,resize成合适的的大小
(x, y, w, h) = cv2.boundingRect(c)
roi = group[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
cv_show1('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.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)
























# 打印结果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv_show("Image", image)
#cv2.waitKey(0)
Credit Card Type: Visa
Credit Card #: 4000123456789010

参考
边栏推荐
- 【阶段人生总结】放弃考研,参与到工作中,已经顺利毕业了,昨天刚领毕业证
- Vnctf2022 open web gocalc0
- About the use of HTTP cache validation last modified and Etag
- Microservice development steps (Nacos)
- 2022-2-15 learning the imitation Niuke project - Section 3 post details
- Fundamentals of C language
- Markdown编辑器使用基本语法
- TypeScript: let
- 111. Minimum depth of binary tree
- Semiconductor foundation of binary realization principle
猜你喜欢

Blog recommendation | in depth study of message segmentation in pulsar

241. Design priorities for operational expressions

C learning notes (5) class and inheritance

【牛客网刷题系列 之 Verilog快速入门】~ 使用函数实现数据大小端转换

Minimum spanning tree and bipartite graph in graph theory (acwing template)

手把手带你入门 API 开发
![[leetcode 324] swing sorting II thinking + sorting](/img/cb/26d89e1a1f548b75a5ef9f29eebeee.png)
[leetcode 324] swing sorting II thinking + sorting

Fundamentals of C language

SQLAchemy 常用操作

竣达技术丨室内空气环境监测终端 pm2.5、温湿度TVOC等多参数监测
随机推荐
[dynamic programming] interval dp:p1005 matrix retrieval
关于重载运算符的再整理
Reorganize the trivial knowledge points at the end of the term
30 Devops interview questions and answers
Zabbix API与PHP的配置
NPDP产品经理国际认证报名有什么要求?
Redis installation and setting up SSDB master-slave environment under Ubuntu 14.04
QT capture interface is displayed as picture or label
Solid smart contract development - easy to get started
Semiconductor foundation of binary realization principle
Minimum spanning tree and bipartite graph in graph theory (acwing template)
JVM第二话 -- JVM内存模型以及垃圾回收
职场太老实,总被欺负怎么办?
Internet hospital system source code hospital applet source code smart hospital source code online consultation system source code
643. Maximum average number of subarrays I
官宣:Apache Doris 顺利毕业,成为 ASF 顶级项目!
Demand prioritization method based on value quantification
Today, with the popularity of micro services, how does service mesh exist?
期末琐碎知识点再整理
JVM second conversation -- JVM memory model and garbage collection