挑战杯 基于机器视觉的银行卡识别系统 - opencv python

2024-03-03 18:20

本文主要是介绍挑战杯 基于机器视觉的银行卡识别系统 - opencv python,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 前言

🔥 优质竞赛项目系列,今天要分享的是

基于深度学习的银行卡识别算法设计

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

2 算法设计流程

银行卡卡号识别技术原理是先对银行卡图像定位,保障获取图像绝对位置后,对图像进行字符分割,然后将分割完成的信息与模型进行比较,从而匹配出与其最相似的数字。主要流程图如图

在这里插入图片描述

1.银行卡号图像
由于银行卡卡号信息涉及个人隐私,作者很难在短时间内获取大量的银行卡进行测试和试验,本文即采用作者个人及模拟银行卡进行卡号识别测试。

2.图像预处理
图像预处理是在获取图像后必须优先进行的技术性处理工作,先对银行卡卡号图像进行色彩处理,具体做法与流程是先将图像灰度化,去掉图像识别上无用的信息,然后利用归一化只保留有效的卡号信息区域。

3.字符分割
字符分割是在对图像进行预处理后,在获取有效图像后对有效区域进行进一步细化处理,将图像分割为最小识别字符单元。

4.字符识别
字符识别是在对银行卡卡号进行字符分割后,利用图像识别技术来对字符进行分析和匹配,本文作者利用的模板匹配方法。

2.1 颜色空间转换

由于银行卡卡号识别与颜色无关,所以银行卡颜色是一个无用因素,我们在图像预处理环节要先将其过滤掉。另外,图像处理中还含有颜色信息,不仅会造成空间浪费,增加运算量,降低系统的整体效率,还会给以后的图像分析和处理带来干扰。因此,有必要利用灰度处理来滤除颜色信息。

灰度处理的实质是将颜色信息转化为亮度信息,即将原始的三维颜色信息还原为一维亮度信息。灰度化的思想是用灰度值g来表示原始彩色图像的R(绿色)、g(红色)和B(蓝色)分量的值,具体的流程设计如图

在这里插入图片描述

2.2 边缘切割

对于采集到的银行卡号图像,由于背景图案的多样性和卡号字体的不同,无法直接对卡号图像进行分割。分割前要准确定位卡号,才能得到有效区域。数字字符所在的区域有许多像素。根据该特征,通过设置阈值来确定原始图像中卡号图像的区域。银行卡图像的切边处理设计如图

在这里插入图片描述

2.3 模板匹配

模板匹配是一种将需要识别的字符与已有固定模板进行匹配的算法技术,该技术是将已经切割好的字符图像逐个与模板数字图像进行对比分析,其原理就是通过数字相似度来衡量两个字符元素,将目标字符元素逐个与模板数字图像进行匹配,找到最接近的数字元素即可。匹配计算量随特征级别的增加而减少。根据第一步得到的特征,选择第二种相关计算方法来解决图像匹配问题。银行卡模板匹配流程设计如图

在这里插入图片描述

2.4 卡号识别

银行卡卡号识别有其独有的特性,因为目前市面上大多数银行卡卡号是凹凸不平的数字形式,如果使用传统的计算机字符识别技术已显然不适用,本文针对银行卡此类特点,研究了解决此类问题的识别方案。从银行卡待识别的凸凹字符进行预处理,然后根据滑块算法逐个窗口对银行卡字符进行匹配识别,卡号识别一般从切割后的图像最左端开始,设定截图选定框大小为64*48像素,因为银行卡所需要识别的字符一般为45像素左右。故而以此方式循环对卡片上所有数字进行匹配、识别,如果最小值大于设置的阈值,我们将认为这里没有字符,这是一个空白区域,并且不输出字符。同时,窗口位置J向下滑动,输出f<19&&j;+20<图像总长度并判断,最后循环得到字符数f、j。

在这里插入图片描述

3 银行卡字符定位 - 算法实现

首先就是将整张银行卡号里面的银行卡号部分进行识别,且分出来,这一个环节学长用的技术就是faster-rcnn的方法

将目标识别部分的银行卡号部门且分出来,进行保存

主程序的代码如下(非完整代码):

#!/usr/bin/env pythonfrom __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport argparseimport osimport cv2import matplotlib.pyplot as pltimport numpy as npimport tensorflow as tffrom lib.config import config as cfgfrom lib.utils.nms_wrapper import nmsfrom lib.utils.test import im_detectfrom lib.nets.vgg16 import vgg16from lib.utils.timer import Timeros.environ["CUDA_VISIBLE_DEVICES"] = '0'   #指定第一块GPU可用config = tf.ConfigProto()config.gpu_options.per_process_gpu_memory_fraction = 0.8  # 程序最多只能占用指定gpu50%的显存config.gpu_options.allow_growth = True      #程序按需申请内存sess = tf.Session(config = config)CLASSES = ('__background__','lb')NETS = {'vgg16': ('vgg16_faster_rcnn_iter_70000.ckpt',), 'res101': ('res101_faster_rcnn_iter_110000.ckpt',)}DATASETS = {'pascal_voc': ('voc_2007_trainval',), 'pascal_voc_0712': ('voc_2007_trainval+voc_2012_trainval',)}def vis_detections(im, class_name, dets, thresh=0.5):"""Draw detected bounding boxes."""inds = np.where(dets[:, -1] >= thresh)[0]if len(inds) == 0:returnim = im[:, :, (2, 1, 0)]fig, ax = plt.subplots(figsize=(12, 12))ax.imshow(im, aspect='equal')sco=[]for i in inds:score = dets[i, -1]sco.append(score)maxscore=max(sco)# print(maxscore)成绩最大值for i in inds:# print(i)score = dets[i, -1]if score==maxscore:bbox = dets[i, :4]# print(bbox)#目标框的4个坐标img = cv2.imread("data/demo/"+filename)# img = cv2.imread('data/demo/000002.jpg')sp=img.shapewidth = sp[1]if bbox[0]>20 and bbox[2]+20<width:cropped = img[int(bbox[1]):int(bbox[3]), int(bbox[0]-20):int(bbox[2])+20] # 裁剪坐标为[y0:y1, x0:x1]if bbox[0]<20 and bbox[2]+20<width:cropped = img[int(bbox[1]):int(bbox[3]), int(bbox[0]):int(bbox[2])+20] # 裁剪坐标为[y0:y1, x0:x1]if bbox[0] > 20 and bbox[2] + 20 > width:cropped = img[int(bbox[1]):int(bbox[3]), int(bbox[0] - 20):int(bbox[2])]  # 裁剪坐标为[y0:y1, x0:x1]path = 'cut1/'# 重定义图片的大小res = cv2.resize(cropped, (1000, 100), interpolation=cv2.INTER_CUBIC)  # dsize=(2*width,2*height)cv2.imwrite(path+str(i)+filename, res)ax.add_patch(plt.Rectangle((bbox[0], bbox[1]),bbox[2] - bbox[0],bbox[3] - bbox[1], fill=False,edgecolor='red', linewidth=3.5))ax.text(bbox[0], bbox[1] - 2,'{:s} {:.3f}'.format(class_name, score),bbox=dict(facecolor='blue', alpha=0.5),fontsize=14, color='white')ax.set_title(('{} detections with ''p({} | box) >= {:.1f}').format(class_name, class_name,thresh),fontsize=14)plt.axis('off')plt.tight_layout()plt.draw()def demo(sess, net, image_name):"""Detect object classes in an image using pre-computed object proposals."""# Load the demo imageim_file = os.path.join(cfg.FLAGS2["data_dir"], 'demo', image_name)im = cv2.imread(im_file)# Detect all object classes and regress object boundstimer = Timer()timer.tic()scores, boxes = im_detect(sess, net, im)timer.toc()print('Detection took {:.3f}s for {:d} object proposals'.format(timer.total_time, boxes.shape[0]))# Visualize detections for each classCONF_THRESH = 0.1NMS_THRESH = 0.1for cls_ind, cls in enumerate(CLASSES[1:]):cls_ind += 1  # because we skipped backgroundcls_boxes = boxes[:, 4 * cls_ind:4 * (cls_ind + 1)]cls_scores = scores[:, cls_ind]# print(cls_scores)#一个300个数的数组#np.newaxis增加维度  np.hstack将数组拼接在一起dets = np.hstack((cls_boxes,cls_scores[:, np.newaxis])).astype(np.float32)keep = nms(dets, NMS_THRESH)dets = dets[keep, :]vis_detections(im, cls, dets, thresh=CONF_THRESH)def parse_args():"""Parse input arguments."""parser = argparse.ArgumentParser(description='Tensorflow Faster R-CNN demo')parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16 res101]',choices=NETS.keys(), default='vgg16')parser.add_argument('--dataset', dest='dataset', help='Trained dataset [pascal_voc pascal_voc_0712]',choices=DATASETS.keys(), default='pascal_voc')args = parser.parse_args()return argsif __name__ == '__main__':args = parse_args()# model pathdemonet = args.demo_netdataset = args.dataset#tfmodel = os.path.join('output', demonet, DATASETS[dataset][0], 'default', NETS[demonet][0])tfmodel = r'./default/voc_2007_trainval/cut1/vgg16_faster_rcnn_iter_8000.ckpt'# 路径异常提醒if not os.path.isfile(tfmodel + '.meta'):print(tfmodel)raise IOError(('{:s} not found.\nDid you download the proper networks from ''our server and place them properly?').format(tfmodel + '.meta'))# set configtfconfig = tf.ConfigProto(allow_soft_placement=True)tfconfig.gpu_options.allow_growth = True# init sessionsess = tf.Session(config=tfconfig)# load networkif demonet == 'vgg16':net = vgg16(batch_size=1)# elif demonet == 'res101':# net = resnetv1(batch_size=1, num_layers=101)else:raise NotImplementedErrornet.create_architecture(sess, "TEST", 2,tag='default', anchor_scales=[8, 16, 32])saver = tf.train.Saver()saver.restore(sess, tfmodel)print('Loaded network {:s}'.format(tfmodel))# # 文件夹下所有图片进行识别# for filename in os.listdir(r'data/demo/'):#     im_names = [filename]#     for im_name in im_names:#         print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')#         print('Demo for data/demo/{}'.format(im_name))#         demo(sess, net, im_name)##     plt.show()# 单一图片进行识别filename = '0001.jpg'im_names = [filename]for im_name in im_names:print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')print('Demo for data/demo/{}'.format(im_name))demo(sess, net, im_name)plt.show()

效果如下:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4 字符分割

将切分出来的图片进行保存,然后就是将其进行切分:

主程序的代码和上面第一步的步骤原理是相同的,不同的就是训练集的不同设置

效果图如下:

在这里插入图片描述

5 银行卡数字识别

仅部分代码:

import osimport tensorflow as tffrom PIL import Imagefrom nets2 import nets_factoryimport numpy as npimport matplotlib.pyplot as plt# 不同字符数量CHAR_SET_LEN = 10# 图片高度IMAGE_HEIGHT = 60# 图片宽度IMAGE_WIDTH = 160# 批次BATCH_SIZE = 1# tfrecord文件存放路径TFRECORD_FILE = r"C:\workspace\Python\Bank_Card_OCR\demo\test_result\tfrecords/1.tfrecords"# placeholderx = tf.placeholder(tf.float32, [None, 224, 224])os.environ["CUDA_VISIBLE_DEVICES"] = '0'   #指定第一块GPU可用config = tf.ConfigProto()config.gpu_options.per_process_gpu_memory_fraction = 0.5  # 程序最多只能占用指定gpu50%的显存config.gpu_options.allow_growth = True      #程序按需申请内存sess = tf.Session(config = config)# 从tfrecord读出数据def read_and_decode(filename):# 根据文件名生成一个队列filename_queue = tf.train.string_input_producer([filename])reader = tf.TFRecordReader()# 返回文件名和文件_, serialized_example = reader.read(filename_queue)features = tf.parse_single_example(serialized_example,features={'image' : tf.FixedLenFeature([], tf.string),'label0': tf.FixedLenFeature([], tf.int64),})# 获取图片数据image = tf.decode_raw(features['image'], tf.uint8)# 没有经过预处理的灰度图image_raw = tf.reshape(image, [224, 224])# tf.train.shuffle_batch必须确定shapeimage = tf.reshape(image, [224, 224])# 图片预处理image = tf.cast(image, tf.float32) / 255.0image = tf.subtract(image, 0.5)image = tf.multiply(image, 2.0)# 获取labellabel0 = tf.cast(features['label0'], tf.int32)return image, image_raw, label0# 获取图片数据和标签image, image_raw, label0 = read_and_decode(TFRECORD_FILE)# 使用shuffle_batch可以随机打乱image_batch, image_raw_batch, label_batch0 = tf.train.shuffle_batch([image, image_raw, label0], batch_size=BATCH_SIZE,capacity=50000, min_after_dequeue=10000, num_threads=1)# 定义网络结构train_network_fn = nets_factory.get_network_fn('alexnet_v2',num_classes=CHAR_SET_LEN * 1,weight_decay=0.0005,is_training=False)with tf.Session() as sess:# inputs: a tensor of size [batch_size, height, width, channels]X = tf.reshape(x, [BATCH_SIZE, 224, 224, 1])# 数据输入网络得到输出值logits, end_points = train_network_fn(X)# 预测值logits0 = tf.slice(logits, [0, 0], [-1, 10])predict0 = tf.argmax(logits0, 1)# 初始化sess.run(tf.global_variables_initializer())# 载入训练好的模型saver = tf.train.Saver()saver.restore(sess, '../Cmodels/model/crack_captcha1.model-6000')# saver.restore(sess, '../1/crack_captcha1.model-2500')# 创建一个协调器,管理线程coord = tf.train.Coordinator()# 启动QueueRunner, 此时文件名队列已经进队threads = tf.train.start_queue_runners(sess=sess, coord=coord)for i in range(6):# 获取一个批次的数据和标签b_image, b_image_raw, b_label0 = sess.run([image_batch,image_raw_batch,label_batch0])# 显示图片img = Image.fromarray(b_image_raw[0], 'L')plt.imshow(img)plt.axis('off')plt.show()# 打印标签print('label:', b_label0)# 预测label0 = sess.run([predict0], feed_dict={x: b_image})# 打印预测值print('predict:', label0[0])# 通知其他线程关闭coord.request_stop()# 其他所有线程关闭之后,这一函数才能返回coord.join(threads)

最终实现效果:

在这里插入图片描述

最后

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

这篇关于挑战杯 基于机器视觉的银行卡识别系统 - opencv python的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/770498

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip