基于机器视觉的火车票识别系统 计算机竞赛

文章目录

  • 0 前言
  • 1 课题意义
    • 课题难点:
  • 2 实现方法
    • 2.1 图像预处理
    • 2.2 字符分割
    • 2.3 字符识别
      • 部分实现代码
  • 3 实现效果
  • 最后

0 前言

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

基于机器视觉的火车票识别系统

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

🧿 更多资料, 项目分享:

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一个Operation
        print("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 实现效果

车票图
在这里插入图片描述
识别效果:
在这里插入图片描述

最后

🧿 更多资料, 项目分享:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/106804.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

反恐精英CS1.6forMac/win中文版:动作射击游戏的巅峰之作

的游戏爱好者们,今天我们要向大家推荐一款让人热血沸腾的第一人称动作射击游戏——反恐精英CS1.6!这款游戏承载了无数玩家的童年记忆,更是射击游戏领域中的佼佼者。 一、还原度极高的场景与道具 反恐精英CS1.6在场景和道具的还原度上做到了极…

在Mac上安装MongoDB 5.0

MongoDB 5.0安装 1、环境描述 操作系统:macOS 14.0 (23A344) 2、安装MongoDB 2.1、tar解压包安装 下载地址:Download MongoDB Community Server | MongoDB 创建一个目录,以便数据库将文件放入其中。(默认情况下,数据…

【axios】axios的基本使用

一、 Axios简介 1、 Axios是什么? Axios是一个基于promise的HTTP库,类似于jQuery的ajax,用于http请求。可以应用于浏览器端和node.js,既可以用于客户端,也可以用于node.js编写的服务端。 2.、Axios特性 支持Promis…

王道p149 7.二叉树按二叉链表形式存储,写一个判别给定二叉树是否是完全二叉树的算法(c语言代码实现)

采用层次遍历算法,将所有结点加入队列(包括空结点)。 如果没有左孩子,就看有没有右孩子,如果有右孩子,那么不为完全二叉树。 如果有左孩子,且之前不存在缺孩子的结点,左孩子进队,如果有右孩子…

零售数据分析模板分享(通用型)

零售数据来源多,数据量大,导致数据的清洗整理工作量大,由于零售的特殊性,其指标计算组合更是多变,进一步导致了零售数据分析工作量激增,往往很难及时分析数据,发现问题。那怎么办?可…

FL Studio21.2中文版多少钱?值得下载吗

水果,全称Fruity Loop Studio,简称FL Studio。是一款全能的音乐制作软件,经过二十多年的演化更迭,其各项功能非常的先进。其开创性的Pat\song模式,也为初学者的学习提供了便利。那么水果音乐制作软件需要多少钱呢&…

JAVA实现校园二手交易系统 开源

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手商品档案管理模块2.3 商品预约管理模块2.4 商品预定管理模块2.5 商品留言板管理模块2.6 商品资讯管理模块 三、实体类设计3.1 用户表3.2 二手商品表3.3 商品预约表3.4 商品预定表3.5 留言表3.6 资讯…

【0基础学Java第一课】-- 初始Java

目录 1. 初识java1.1 Java是什么1.2 Java应用领域1.3 Java语言发展简史1.4 Java语言特性1.5 JRE与JDK1.6 Java开发环境1.6.1 安装JDK1.6.2 配置环境变量 1.7 初始Java中main函数1.7.1 JDK、JRE、JVM之间的关系 1.8 注释1.9 标识符1.10 关键字 1. 初识java 1.1 Java是什么 Jav…

计算机操作系统重点概念整理-第二章 进程管理【期末复习|考研复习】

第二章 进程管理 【期末复习|考研复习】 计算机操作系统系列文章传送门: 第一章 计算机系统概述 第二章 进程管理 第三章 进程同步 第四章 内存管理 第五章 文件管理 第六章 输出输出I/O管理 文章目录 第二章 进程管理 【期末复习|考研复习】前言二、进程管理2.1进…

Leetcode—66.加一【简单】

2023每日刷题(十一) Leetcode—66.加一 实现代码1 /*** Note: The returned array must be malloced, assume caller calls free().*/ int* plusOne(int* digits, int digitsSize, int* returnSize){int num 0;int i 0;int arr[110] {0};// 进位标识…

Spring 更简单的读取和存储对象

引言 在上一章节中,我们通过设置配置文件的方式简单实现了 Spring 中 Bean 对象的存取,但是相比之下,每次进行对象的注册和获取还是相对麻烦的,那么有没有更简单优雅的方式呢?答案当然是有的:在 Spring 中…

如何分离一个要素的shp矢量文件:利用ArcGIS分割工具

下面介绍如何用ArcGIS对含有多个分离区域的一整个面要素进行分割 如下图,现在想要将下方的长形shp提取出来,首先打开shp文件: 右击空白处查看该矢量文件的投影信息: 在文件夹中新建shp文件,设置一样的投影&#xff1a…

MySQL数据库——视图的更新、视图作用以及案例

目录 视图的更新 介绍 示例 视图作用 案例 视图的更新 介绍 要使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。 如果视图包含以下任何一项,则该视图不可更新: 聚合函数或窗口函数(SUM()、MIN()、MAX()…

蓝桥杯 Java 青蛙过河

import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改/**二分法从大(n)到小找足够小的步长前缀和记录每个位置的前面有的总石头数(一个石头表示可以容纳一个青蛙,一位置有多少个石头hi就是多少)&…

【动态基础】从暴力递归到动态规划

C面经汇总 系列综述: 目的:本系列是个人整理为了秋招和实习面试的,整理期间苛求每个知识点,平衡背诵量与深入程度。 来源:材料主要源于算法大神(左程云)教你从暴力递归到动态规划进行的&#xf…

文件上传预览下载

文件上传的表单必须满足三个条件: 1.表单组件标签只能用:<input type"file" value"xxx">会自动弹框让用户选择文件 2.请求方式只能用post 3.表单编码格式只能用:mutipart/form-data 根据HTTP协议规定,浏览器每次向后台提交参数,都会对参数进行统一…

【软件安装环境配置】vscode 安装界面没有出现安装路径的选择 的解决,以及vscode的删除的问题

由于vscode 没有删除干净&#xff0c;就会出现vscode 安装的时候&#xff0c;没有出现安装路径的界面&#xff0c;所以可以来到vscode的安装路径&#xff0c;点击 unins000.exe 文件就可以 实现将vscode 相关的文件删除&#xff0c; 如果是删除了整个vscode 安装下的文件&…

GPT做SQL查询引擎的自然语言

目录 面向企业查询的生成式人工智能 步骤1&#xff1a;将示例数据转换为单字符字符串 步骤2&#xff1a;为大型语言模型&#xff08;LM&#xff09;创建提示符 步骤3&#xff1a;将数据发送到OpenAI的API 步骤4&#xff1a;执行GPT返回的SQL代码的结果 步骤5(可选)&#…

Webpack简介及打包演示

Webpack 是一个静态模块打包工具&#xff0c;从入口构建依赖图&#xff0c;打包有关的模块&#xff0c;最后用于展示你的内容 静态模块&#xff1a;编写代码过程中的&#xff0c;html&#xff0c;css&#xff0c; js&#xff0c;图片等固定内容的文件 打包过程&#xff0c;注…

智慧巡查平台(Ionic/Vite/Vue3 移动端) 问题记录

目录 1.环境搭建 1.1 安装 node 16 版本 1.2 安装 ionic7 1.3 创建 vue 项目 2.index.html 3.main.ts 3.1 如何默认使用 ios 样式&#xff1f; 3.2 如何使用 ElmentPlus 国际化&#xff1f; 4.router/xxx 5.打包二三事 5.1 添加打包相关文件 5.1.1 .env.developmen…