目录
前言
课题背景和意义
实现技术思路
实现效果图样例
大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过和节省时间与精力投入到更重要的就业和考试中去,学长分享优质的选题经验和毕设项目与技术思路。
对毕设有任何疑问都可以问学长哦!
大家好,这里是海浪学长毕设专题,本次分享的课题是
基于机器视觉的银行卡号识别系统
现在很多需要录入银行卡信息才能办理的业务仍然停留在纯手工录入的方式,流程繁琐又耗时,造成业务办理的等待时间长,流程效率低,顾客抱怨增多,运营成本也在不断增大等问题。与手工输入银行卡号相比,扫描银行卡扫描银行卡号识别SDK具备精确度高、识别速度快、抗干扰性强等特点,能够识别市面上几乎所有的银行卡(含凸字银行卡和平面银行卡等),扫描银行卡扫描银行卡号识别SDK采用视频预览识别方式,无需按拍摄按钮,直接通过视频预览识别。
1、对图像进行预处理(灰度,二值,)
2、计算找到每个数字的轮廓并排序
3、将每个数字的小照片剪切后依次保存到一个字典中(键=值)
图像预处理,是将每一个文字图像分检出来交给识别模块识别,这一过程称为图像预处理。在图像分析中,对输入图像进行特征抽取、分割和匹配前所进行的处理。
图像预处理的主要目的是消除图像中无关的信息,恢复有用的真实信息,增强有关信息的可检测性和最大限度地简化数据,从而改进特征抽取、图像分割、匹配和识别的可靠性。
# 定义函数方便调用,绘图展示
def cv_show(name,img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread(args["template"]) # 读取一个模板图像
cv_show('img',img)
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图
cv_show('ref',ref)
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1] # 再转化为二值图像
cv_show('ref',ref)
定义排序函数 和 按比例resize图像大小的函数,此部分由工具包引入使用便捷
import cv2
#定义轮廓排序函数
def sort_contours(cnts, method="left-to-right"):
reverse = False
i = 0
if method == "right-to-left" or method == "bottom-to-top":
reverse = True
return cnts, boundingBoxes
#定义按比例放大缩小图像的函数
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
r = height / float(h) #计算出现在的高与原来的高的比
dim = (int(w * r), height) #得到对应图像宽高
else:
r = width / float(w) #计算出现在的宽与原来的宽的比
dim = (width, int(h * r)) #得到对应图像宽高
resized = cv2.resize(image, dim, interpolation=inter)
return resized
# 计算轮廓
#cv2.findContours()函数接受的参数为二值图,黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓
refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,0,255),3) #画轮廓
cv_show('img',img)
#print (np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {} #定义一个空字典
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts): # 数字的下标和数值是一样的
# 计算外接矩形并且resize成合适大小
(x, y, w, h) = cv2.boundingRect(c)
roi = ref[y:y + h, x:x + w] #轮廓i的外接矩形
roi = cv2.resize(roi, (57, 88)) #将外接矩形大小调整为一固定大小
#cv_show('roi',roi)
# 每一个数字对应每一个模板
digits[i] = roi #i是键,模板是值,并且二者大小相同,添加到字典中
1、对图像进行灰度化并且调整大小
2、对图像进行处理形态学处理和其他操作,使图像中字符连成块状
3、找到卡号所在位置,并提取轮廓
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
#读取输入图像,预处理
image = cv2.imread('Card.jpg')
cv_show('image',image)
image = myutils.resize(image, width=300) #调整大小
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #灰度化
cv_show('gray',gray)
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) #礼帽操作,突出更明亮的区域
cv_show('tophat',tophat)
#求水平方向的梯度,检测边界
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1) #ksize=-1相当于用3*3的Scharr滤波器
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',gradX)
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) #通过闭操作(先膨胀,再腐蚀)将数字连在一起(用较大的核)
cv_show('gradX',gradX)
thresh = cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] #THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
cv_show('thresh',thresh)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作,去除杂质
cv_show('thresh',thresh)
我是海浪学长,创作不易,欢迎点赞、关注、收藏、留言。
毕设帮助,疑难解答,欢迎打扰!