深度学习火车票识别系统 计算机竞赛
文章目录
- 0 前言
- 1 课题意义
- 课题难点:
- 2 实现方法
- 2.1 图像预处理
- 2.2 字符分割
- 2.3 字符识别
- 部分实现代码
- 3 实现效果
- 4 最后
0 前言
🔥 优质竞赛项目系列,今天要分享的是
🚩 图像识别 火车票识别系统
该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:4分
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
1 课题意义

目前火车乘务员在卧铺旅客在上车前为其提供将火车票换成位置信息卡服务,在旅客上车前,由于上车人数多,而且大多数旅客都携带大量行李物品,而且乘车中老人和小孩也较多。在换卡这一过程中,人员拥挤十分厉害,而且上火车时,火车门窄阶梯也较陡,危险系数十分高。乘务员维持秩序十分困难。换卡之后,在旅客下车之前乘务员又要将位置信息卡换成火车票。这一过程冗长且对于旅客基本没有任何有用的意义。如果通过光学符识别软件,乘务员利用ipad等电子产品扫描采集火车票图像,读取文本图像,通过识别算法转成文字,将文字信息提取出来,之后存储起来,便于乘务员统计查看,在旅客到站是,系统自动提醒乘务员某站点下车的所有旅客位置信息。随着铁路交通的不断优化,车次与旅客人数的增加,火车票免票系统将更加便捷,为人们带来更好的服务。
课题难点:
由于火车票票面文字识别属于多种字体混排,低品质的专用印刷汉子识别。火车票文字笔画粘连,断裂,识别复杂度高,难度大,采用目前较好的OCR技术都比较难以实现。
2 实现方法
2.1 图像预处理
火车票经过扫描装置火车照相机等装置将图像传递到计算机,经过灰度处理保存为一幅灰度图。如果要对火车票进行后期的识别,那么就一定要对图像做二值化,之后再对二值化的图像进行版面分析,确定我们所需要的信息所在,之后才能进行单个字符的分割,才能对字符做提取特征点的工作,之后按照我们对比确定的规则来进行判决从而达到识别效果。
由于火车票容易被污损、弯折,而且字符的颜色也是有所不同,火车票票号是红色,而其他信息显示则为黑色,票面的背景包括红色和蓝色两种彩色,这些特点都使得火车票的文字识别不同于一般的文字识别。在识前期,要对火车票图像做出特定的处理才能很好的进行后续的识别。本次课题所研究的预处理有平常所处理的二值化,平滑去噪之外还需要针对不同字符颜色来进行彩色空间上的平滑过滤。
预处理流程如下所示

2.2 字符分割
字符分割就是在版面分析后得到的文本块切分成为文字行,之后再将行分割成单个字符,来进行后续的字符识别。这是OCR系统里至关重要的一环,直接影响识别效果。字符分割的主流方式有三种,一种是居于图像特种来寻找分割的准则,这是从结构角度进行分析切割。另一种方式是根据识别效果反馈来确认分割结果有无问题,这种方式是基于识别的切分。还有一种整体切分方式,把字符串当做整体,系统进行以词为基础的识别比并非字识别,一般这一方式要根据先验知识来进行辅助判断。
分割效果如下图所示:


2.3 字符识别
中文/数字/英文 识别目前最高效的方法就是使用深度学习算法进行识别。
字符识别对于深度学习开发者来说是老生常谈了,这里就不在复述了;
网络可以视为编解码器结构,编码器由特征提取网络ResneXt-50和双向长短时记忆网络(BiLSTM)构成,解码器由加入注意力机制的长短时记忆网络(LSTM)构成。网络结构如下图所示。

网络训练流程如下:

部分实现代码
这里学长提供一个简单网络字符识别的训练代码:
(需要完整工程及代码的同学联系学长获取)
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
#1、开始建立一个图
sess = tf.InteractiveSession()#启动一个交互会话
x = tf.placeholder(tf.float32, shape=[None, 784])#x和y_都用一个占位符表示
y_ = tf.placeholder(tf.float32, shape=[None, 10])W = tf.Variable(tf.zeros([784, 10]))#W和b因为需要改变,所以定义为初始化为0的变量
b = tf.Variable(tf.zeros(10))#2、建立预测部分的操作节点
y = tf.matmul(x,W) + b #计算wx+b
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)) #计算softmax交叉熵的均值#3、现在已经得到了损失函数,接下来要做的就是最小化这一损失函数,这里用最常用的梯度下降做
# 为了用到前几节说过的内容,这里用学习率随训练下降的方法执行
global_step = tf.Variable(0, trainable = False)#建立一个可变数,而且这个变量在计算梯度时候不被影响,其实就是个全局变量
start_learning_rate = 0.5#这么写是为了清楚
#得到所需的学习率,学习率每100个step进行一次变化,公式为decayed_learning_rate = learning_rate * decay_rate ^(global_step / decay_steps)
learning_rate = tf.train.exponential_decay(start_learning_rate, global_step, 10, 0.9, staircase=True)train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(cross_entropy)#梯度下降最小化交叉熵
#这是因为在交互的Session下可以这样写Op.run(),还可以sess.run(tf.global_variables_initializer())
tf.global_variables_initializer().run()#初始化所有变量#iteration = 1000, Batch_Size = 100
for _ in range(1000):batch = mnist.train.next_batch(100)#每次选出100个数据train_step.run(feed_dict = {x:batch[0], y_: batch[1]})#给Placeholder填充数据就可以了correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) #首先比较两个结果的差异
#这时的correct_prediction应该类似[True, False, True, True],然后只要转为float的形式再求加和平均就知道准确率了
#这里的cast是用于形式转化
accuracy = tf.reduce_mean(tf.cast(correct_prediction, dtype=tf.float32))
#打印出来就可以了,注意这个时候accuracy也只是一个tensor,而且也只是一个模型的代表,还需要输入数据
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))sess.close()#首先把要重复用的定义好
def weight_variable(shape):initial = tf.truncated_normal(shape=shape, stddev=0.1)return tf.Variable(initial)
def bias_variable(shape):initial = tf.constant(0.1, shape=shape)#常量转变量,return tf.Variable(initial)
def conv2d(x, f):return tf.nn.conv2d(x, f, strides=[1,1,1,1], padding='SAME')
def max_pool_22(x):return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')sess = tf.InteractiveSession()#启动一个交互会话
x = tf.placeholder(tf.float32, shape=[None, 784])#x和y_都用一个占位符表示
y_ = tf.placeholder(tf.float32, shape=[None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])
#第一层:
#1、设计卷积核1
fW1 = weight_variable([5,5,1,32])#[height, weight, in_channel, out_channel]
fb1 = bias_variable([32])#2、卷积加池化
h1 = tf.nn.relu(conv2d(x_image,fW1)+ fb1)
h1_pool = max_pool_22(h1)#第二层
fW2 = weight_variable([5,5,32,64])#[height, weight, in_channel, out_channel]
fb2 = bias_variable([64])h2 = tf.nn.relu(conv2d(h1_pool,fW2)+ fb2)
h2_pool = max_pool_22(h2)#全部变成一维全连接层,这里因为是按照官方走的,所以手动计算了经过第二层后的图片尺寸为7*7
#来定义了一个wx+b所需的w和b的尺寸,注意这里的W和b不是卷积所用的了
h2_pool_flat = tf.reshape(h2_pool, [-1, 7*7*64])#首先把数据变成行表示
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_fc1 = tf.nn.relu(tf.matmul(h2_pool_flat, W_fc1) + b_fc1)#定义dropout,选择性失活,首先指定一个失活的比例
prob = tf.placeholder(tf.float32)
h_dropout = tf.nn.dropout(h_fc1, prob)#最后一个全连接层,输出10个值,用于softmax
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv = tf.matmul(h_dropout, W_fc2) + b_fc2#梯度更新,这里采用另一种优化方式AdamOptimizer
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))#初始化
sess.run(tf.global_variables_initializer())
for i in range(2000):batch = mnist.train.next_batch(50)if i%100 == 0:train_accuracy = accuracy.eval(feed_dict = {x:batch[0],y_:batch[1], prob:1.0}) #这里是计算accuracy用的eval,不是在run一个Operationprint("step %d, training accuracy %g"%(i, train_accuracy))train_step.run(feed_dict={x: batch[0], y_: batch[1], prob: 0.5})
print("test accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, prob: 1.0}) )
3 实现效果
车票图

识别效果:

4 最后
🧿 更多资料, 项目分享:
https://gitee.com/dancheng-senior/postgraduate
相关文章:
深度学习火车票识别系统 计算机竞赛
文章目录 0 前言1 课题意义课题难点: 2 实现方法2.1 图像预处理2.2 字符分割2.3 字符识别部分实现代码 3 实现效果4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 图像识别 火车票识别系统 该项目较为新颖,适…...
C++EasyX之井字棋
视频链接 井字棋 用EasyX和C实现井字棋小游戏 源码及注释 #include<graphics.h>char board_data[3][3] {{-,-,-},{-,-,-},{-,-,-}, };char current_piece O;//检测指定棋子的玩家是否获胜 bool CheckWin(char c) {// 检查每一行for (int i 0; i < 3; i){if (bo…...
12.5_黑马数据结构与算法Java
目录 001 二分查找 算法描述 002 二分查找 算法实现 003 二分查找 问题1 循环条件 004 二分查找 问题2 中间索引 thinking:反码补码原码? thinking:二进制转十进制? thinking:无符号右移? 005 二分…...
【PID学习笔记 5 】控制系统的性能指标之一
写在前面 PID在实际工程中最重要的工作就是调参,那么首先就要了解控制系统的性能指标。上文最后简要介绍了控制系统的基本要求,本文开始将系统学习控制系统的性能指标,内容比较多,初步计划是分三节来讲解。本文重点介绍性能指标的…...
HarmonyOS学习--TypeScript语言学习(三)
本章目录如下 一、条件语句 二、迭代器 三、循环 四、函数 五、类 一、条件语句 条件语句用于基于不同的条件来执行不同的动作。TypeScript 条件语句是通过一条或多条语句的执行结果(True 或 False)来决定执行的代码块。 在 TypeScript 中&#x…...
Matlab 镜像变换(2D)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 镜像变换是一个非常有趣的过程,它有着一个通用的套路(以2D为例):一个点围绕一个给定对称轴的镜像可以通过平移对称轴上一点,然后旋转它,使对称轴与x轴对齐,之后我们将旋转后的点的y坐标置为负,最后再将对称…...
SpringBoot3-快速体验
1、pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…...
计数问题(数位DP)
题目大意:给定一个区间,求该区间内0 ~ 9出现的次数,多次询问,以0 0结束询问 测试用例: 输入: 1 10 44 497 346 542 1199 1748 1496 1403 1004 503 1714 190 1317 854 1976 494 1001 1960 0 0 输出ÿ…...
SQL Server事务(Transaction)
5. 事务(Transaction) 5.1. 事务概念 事务是关系库中不可分割的一系列数据库操作,这些操作必须要么整体成功,要么整体失败。事务维护数据完整性,保证数据库总是处于一致性状态。虽然,各关系库中事务实现和操作的具体细节有所不同,但基本概念和功能完全相同,而具体操作…...
Python语言基础学习大纲(由某大模型生成)
自从上次经丙察察游了一次滇藏线,已有3个没写一篇了。今天利用由某大模型生成的上面这张思维导图,配合这个大模型生成的6000多字拼凑出一篇博文聊以交差。 Python语言概述 一、语言特点 1.语法简单明了 Python的语法简洁易懂,使得编写代码…...
nodejs+vue+微信小程序+python+PHP天天网站书城管理系统的设计与实现-计算机毕业设计推荐
本项目主要分为前台模块与后台模块2个部分,详细描述如下: (1)前台模块 首页: 首页可以起到导航的作用,用户想要了解网站 ,网站首页为用户可以深入了解网站提供了一个平台,它就向一个“导游”…...
工业机器视觉megauging(向光有光)使用说明书(十二,轻量级的visionpro)
关于最后一个工具的介绍:就是这个“相机图像” 我们可以鼠标双击点进去看一看: 在图像上点击,就可以截取一块图像,是可以放大缩小的,这个放大很low,是我以前研究缩放入门时的版本,本想删除&…...
HarmonyOS学习--了解基本工程目录
1.工程级目录 工程的目录结构如下: 其中详细如下: AppScope中存放应用全局所需要的资源文件。entry是应用的主模块,存放HarmonyOS应用的代码、资源等。oh_modules是工程的依赖包,存放工程依赖的源文件。build-profile.json5是工…...
JRT导出协议实现
之前实现了JRT的打印客户端实现,这次实现JRT的导出Excel的客户端实现,这样这套框架就成为完全体了。还是一样的设计,不面向具体业务编程,我喜欢面向协议编程,导出一样定义了一套协议。 协议约定: 然后就是…...
Unity中动态合批
文章目录 前言一、动态合批的规则1、材质相同是合批的前提,但是如果是材质实例的话,则一样无法合批。2、支持不同网格的合批3、动态合批需要网格支持的顶点条件二、我们导入一个模型并且制作一个Shader,来测试动态合批1、我们选择模型的 Mesh…...
逆水行舟!浅谈24届双非本科秋招
逆水行舟!浅谈24届双非本科的秋招 逆水行舟!浅谈24届双非本科的秋招0、背景 -- 写下本文的初衷1、实习 -- 秋招的预备战役1.1 科大讯飞1.2 三七互娱 2、秋招 -- 一场没有硝烟的战争3、总结 -- 做好自己想做的事情 0、背景 – 写下本文的初衷 如题&#…...
vue3请求代理proxy中pathRewrite失效
问题引入 在vue3配置请求代理proxy的时候pathRewrite失效。 有这样一个例子,作用是为了把所有以/api开头的请求代理到后端的路径和端口上,在vue.config.js配置文件中 设置了代理跨域和默认端口。但是重新运行之后发现端口是改了,但是路径仍然…...
练习题——-【学习补档】日期差值
问题描述 描述 有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。 输入描述: 有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD 输出描述: 每组…...
面试问题 --文件描述符和流
文件描述符概述 文件描述符是计算机操作系统中用于标识和访问文件或输入/输出设备的抽象概念。在Unix和类Unix系统中,文件描述符是一个非负整数,用于唯一标识打开的文件或I/O设备。本文将介绍文件描述符的基本概念和在Unix环境中的应用。 基本概念 文…...
离线安装Zabbix的MariaDB报Error: Package: 1:mariadb-server-5.5.68-1.el7.x86 64异常解决方法
离线安装Zabbix,结果在安装MariaDB时候,报出以下异常 Error: Package: 1:mariadb-server-5.5.68-1.el7.x86 64(New) Requires: per(File::Path) Error: Package: perl-IO-Compress-2.061-2.el7.noarch (New) Requires: perl(I0: :Seekable) Error: Pack…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
