竞赛选题 深度学习 opencv python 公式识别(图像识别 机器视觉)

文章目录

  • 0 前言
  • 1 课题说明
  • 2 效果展示
  • 3 具体实现
  • 4 关键代码实现
  • 5 算法综合效果
  • 6 最后

0 前言

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

🚩 基于深度学习的数学公式识别算法实现

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

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:4分
  • 创新点:4分

🧿 更多资料, 项目分享:

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

1 课题说明

手写数学公式识别较传统OCR问题而言,是一个更复杂的二维手写识别问题,其内部复杂的二维空间结构使得其很难被解析,传统方法的识别效果不佳。随着深度学习在各领域的成功应用,基于深度学习的端到端离线数学公式算法,并在公开数据集上较传统方法获得了显著提升,开辟了全新的数学公式识别框架。然而在线手写数学公式识别框架还未被提出,论文TAP则是首个基于深度学习的端到端在线手写数学公式识别模型,且针对数学公式识别的任务特性提出了多种优化。

公式识别是OCR领域一个非常有挑战性的工作,工作的难点在于它是一个二维的数据,因此无法用传统的CRNN进行识别。

在这里插入图片描述

2 效果展示

这里简单的展示一下效果

在这里插入图片描述

在这里插入图片描述

3 具体实现

在这里插入图片描述

神经网络模型是 Seq2Seq + Attention + Beam
Search。Seq2Seq的Encoder是CNN,Decoder是LSTM。Encoder和Decoder之间插入Attention层,具体操作是这样:Encoder到Decoder有个扁平化的过程,Attention就是在这里插入的。具体模型的可视化结果如下

在这里插入图片描述

4 关键代码实现

class Encoder(object):"""Class with a __call__ method that applies convolutions to an image"""def __init__(self, config):self._config = configdef __call__(self, img, dropout):"""Applies convolutions to the imageArgs:img: batch of img, shape = (?, height, width, channels), of type tf.uint8tf.uint8 因为 2^8 = 256,所以元素值区间 [0, 255],线性压缩到 [-1, 1] 上就是 img = (img - 128) / 128Returns:the encoded images, shape = (?, h', w', c')"""with tf.variable_scope("Encoder"):img = tf.cast(img, tf.float32) - 128.img = img / 128.with tf.variable_scope("convolutional_encoder"):# conv + max pool -> /2# 64 个 3*3 filters, strike = (1, 1), output_img.shape = ceil(L/S) = ceil(input/strike) = (H, W)out = tf.layers.conv2d(img, 64, 3, 1, "SAME", activation=tf.nn.relu)image_summary("out_1_layer", out)out = tf.layers.max_pooling2d(out, 2, 2, "SAME")# conv + max pool -> /2out = tf.layers.conv2d(out, 128, 3, 1, "SAME", activation=tf.nn.relu)image_summary("out_2_layer", out)out = tf.layers.max_pooling2d(out, 2, 2, "SAME")# regular conv -> idout = tf.layers.conv2d(out, 256, 3, 1, "SAME", activation=tf.nn.relu)image_summary("out_3_layer", out)out = tf.layers.conv2d(out, 256, 3, 1, "SAME", activation=tf.nn.relu)image_summary("out_4_layer", out)if self._config.encoder_cnn == "vanilla":out = tf.layers.max_pooling2d(out, (2, 1), (2, 1), "SAME")out = tf.layers.conv2d(out, 512, 3, 1, "SAME", activation=tf.nn.relu)image_summary("out_5_layer", out)if self._config.encoder_cnn == "vanilla":out = tf.layers.max_pooling2d(out, (1, 2), (1, 2), "SAME")if self._config.encoder_cnn == "cnn":# conv with stride /2 (replaces the 2 max pool)out = tf.layers.conv2d(out, 512, (2, 4), 2, "SAME")# convout = tf.layers.conv2d(out, 512, 3, 1, "VALID", activation=tf.nn.relu)image_summary("out_6_layer", out)if self._config.positional_embeddings:# from tensor2tensor lib - positional embeddings# 嵌入位置信息(positional)# 后面将会有一个 flatten 的过程,会丢失掉位置信息,所以现在必须把位置信息嵌入# 嵌入的方法有很多,比如加,乘,缩放等等,这里用 tensor2tensor 的实现out = add_timing_signal_nd(out)image_summary("out_7_layer", out)return out

学长编码的部分采用的是传统的卷积神经网络,该网络主要有6层组成,最终得到[N x H x W x C ]大小的特征。

其中:N表示数据的batch数;W、H表示输出的大小,这里W,H是不固定的,从数据集的输入来看我们的输入为固定的buckets,具体如何解决得到不同解码维度的问题稍后再讲;

C为输入的通道数,这里最后得到的通道数为512。

当我们得到特征图之后,我们需要进行reshape操作对特征图进行扁平化,代码具体操作如下:

N    = tf.shape(img)[0]
H, W = tf.shape(img)[1], tf.shape(img)[2] # image
C    = img.shape[3].value                 # channels
self._img = tf.reshape(img, shape=[N, H*W, C])

当我们在进行解码的时候,我们可以直接运用seq2seq来得到我们想要的结果,这个结果可能无法达到我们的预期。因为这个过程会相应的丢失一些位置信息。

位置信息嵌入(Positional Embeddings)

通过位置信息的嵌入,我不需要增加额外的参数的情况下,通过计算512维的向量来表示该图片的位置信息。具体计算公式如下:

在这里插入图片描述

其中:p为位置信息;f为频率参数。从上式可得,图像中的像素的相对位置信息可由sin()或cos表示。

我们知道,sin(a+b)或cos(a+b)可由cos(a)、sin(a)、cos(b)以及sin(b)等表示。也就是说sin(a+b)或cos(a+b)与cos(a)、sin(a)、cos(b)以及sin(b)线性相关,这也可以看作用像素的相对位置正、余弦信息来等效计算相对位置的信息的嵌入。

这个计算过程在tensor2tensor库中已经实现,下面我们看看代码是怎么进行位置信息嵌入。代码实现位于:/model/components/positional.py。

def add_timing_signal_nd(x, min_timescale=1.0, max_timescale=1.0e4):static_shape = x.get_shape().as_list()  # [20, 14, 14, 512]num_dims = len(static_shape) - 2  # 2channels = tf.shape(x)[-1]  # 512num_timescales = channels // (num_dims * 2)  # 512 // (2*2) = 128log_timescale_increment = (math.log(float(max_timescale) / float(min_timescale)) /(tf.to_float(num_timescales) - 1))  # -0.1 / 127inv_timescales = min_timescale * tf.exp(tf.to_float(tf.range(num_timescales)) * -log_timescale_increment)  # len == 128 计算128个维度方向的频率信息for dim in range(num_dims):  # dim == 0; 1length = tf.shape(x)[dim + 1]  # 14 获取特征图宽/高position = tf.to_float(tf.range(length))  # len == 14 计算x或y方向的位置信息[0,1,2...,13]scaled_time = tf.expand_dims(position, 1) * tf.expand_dims(inv_timescales, 0)  # pos = [14, 1], inv = [1, 128], scaled_time = [14, 128] 计算频率信息与位置信息的乘积signal = tf.concat([tf.sin(scaled_time), tf.cos(scaled_time)], axis=1)  # [14, 256] 合并两个方向的位置信息向量prepad = dim * 2 * num_timescales  # 0; 256postpad = channels - (dim + 1) * 2 * num_timescales  # 512-(1;2)*2*128 = 256; 0signal = tf.pad(signal, [[0, 0], [prepad, postpad]])  # [14, 512] 分别在矩阵的上下左右填充0for _ in range(1 + dim):  # 1; 2signal = tf.expand_dims(signal, 0)for _ in range(num_dims - 1 - dim):  # 1, 0signal = tf.expand_dims(signal, -2)x += signal  # [1, 14, 1, 512]; [1, 1, 14, 512]return x

得到公式图片x,y方向的位置信息后,只需要要将其添加到原始特征图像上即可。

5 算法综合效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

6 最后

🧿 更多资料, 项目分享:

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【实用工具】谷歌浏览器插件开发指南

谷歌浏览器插件开发指南涉及以下几个方面: 1. 开发环境准备:首先需要安装Chrome浏览器和开发者工具。进入Chrome应用商店,搜索“Extensions Reloader”和“Manifest Viewer”两个插件进行安装,这两个插件可以方便开发和调试。 2…

国庆作业day6

服务器 #include <my_head.h> #define IP "192.168.101.66" #define PORT 6666 int main(int argc, const char *argv[]) {//创建套接字int fd socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){ERR_MSG("socket");return -1;}struct sockaddr_in s…

Win11 安装 Vim

安装包&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Ru7HhTSotz9mteHug-Yhpw?pwd6666 提取码&#xff1a;6666 双击安装包&#xff0c;一直下一步。 配置环境变量&#xff1a; 先配置系统变量中的path&#xff1a; 接着配置用户变量&#xff1a; 在 cmd 中输入…

图的广度遍历-邻接矩阵实现

description 本题要求实现邻接矩阵存储图的广度优先遍历。 函数接口定义&#xff1a; void BFS(MGraph G,Vertex i); 其中MGraph是邻接矩阵存储的图&#xff0c;定义如下&#xff1a; #define MaxVertexNum 10 /定义最大顶点数/ typedef int Vertex;/* 用顶点下标表示顶点,…

RabbitMQ 5种工作模式介绍和Springboot具体实现

RabbitMQ有5中工作模式&#xff1a;简单模式、工作队列模式、发布/订阅模式、路由模式和主题模式 简单模式&#xff08;Simple Mode&#xff09; 简单模式是最基本的工作模式&#xff0c;也是最简单的模式。在简单模式中&#xff0c;生产者将消息发送到一个队列中&#xff0c;…

这可能是最全的反爬虫及应对方案,再也不怕爬不到数据了

一、什么是反爬虫 网络爬虫&#xff0c;是一个自动提取网页的程序&#xff0c;它为搜索引擎从万维网上下载网页&#xff0c;是搜索引擎的重要组成。但是当网络爬虫被滥用后&#xff0c;互联网上就出现太多同质的东西&#xff0c;原创得不到保护。于是&#xff0c;很多网站开始…

Java项目:高仿12306

github地址&#xff1a;nageoffer/12306: &#x1f525; 官方推荐 &#x1f525; 大学春招、秋招、应届项目&#xff0c;SpringBoot3 Java17 SpringCloud Alibaba Vue3 等技术架构&#xff0c;完成高仿铁路 12306 用户 抢票 订单 支付服务&#xff0c;帮助学生主打就业的…

mysql_config_editor的配置

参考文档&#xff1a; https://mysql.net.cn/doc/refman/8.0/en/mysql-config-editor.html OS上分别有2套库&#xff0c;设置后&#xff0c;通过不使用密码来登录&#xff0c;类似postgres的.pgpass文件 -- 执行一下命令&#xff0c;会要求提示输入密码 mysql_config_edit…

网站强制跳转至国家反诈中心该怎么办?怎么处理?如何解封?

在互联网环境中&#xff0c;网站安全是非常重要的。然而&#xff0c;在实际操作过程中&#xff0c;不少网站可能因内容问题、技术安全漏洞等原因被迫下线甚至跳转至国家反诈骗中心网址。面对这一严峻问题&#xff0c;我们如何有效解决&#xff0c;让网站恢复运行并解除强制跳转…

ES6中字符串的扩展

字符串的遍历器接口 使用for…of for(let x of foo) {console.log(x); } // f; o; oat() ES5中的charAt()方法&#xff0c;返回字符串给定位置的字符。但是不能识别码点大于0xFFFF的字符&#xff0c;at方法可以 includes()、startsWith()、endsWith() 用来确定一个字符串是…

【C++】设计模式

目录 六大原则单例模式工厂模式①简单工厂模式②工厂方法模式③抽象工厂模式 建造者模式代理模式 六大原则 单一责任原则&#xff08;Single Responsibility Principle) 类的职责应该单一&#xff0c;一个方法只做一件事&#xff0c;职责划分清晰&#xff0c;每次改动到最小单…

在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 示例 1&#xff1a…

解决前端二进制流下载的文件(例如:excel)打不开的问题

1. 现在后端请求数据后&#xff0c;返回了一个二进制的数据&#xff0c;我们要把它下载下来。 这是响应的数据&#xff1a; 2. 这是调用接口的地方&#xff1a; uploadOk(){if(this.files.length 0){return this.$Message.warning("请选择上传文件&#xff01;&#xff…

泛洪攻击(Flood Attack)

执行网络攻击&#xff0c;包括 Ping 泛洪攻击&#xff0c;在绝大多数国家/地区都是非法的&#xff0c;它违反了计算机犯罪法律和条例。执行或尝试执行这样的攻击通常会导致法律后果&#xff0c;包括罚款和监禁。因此&#xff0c;这些信息仅供理论学习和了解&#xff0c;绝不应用…

Multi Label Classification with Missing Labels(MLML)的几种loss设计

多标签学习这个方向问题比较多&#xff0c;可以参考多标签学习的新趋势&#xff08;2021 Survey TPAMI&#xff09; 和 部分标签学习和缺失标签学习到底什么异同&#xff1f; 这两篇偏综述性质的解释。本文重点解释下面几个重点问题&#xff1a; Multi Label Classification w…

第十五章 类和对象——友元

生活中你的家有客厅(Public)&#xff0c;有你的卧室(Private) 客厅所有来的客人都可以进去&#xff0c;但是你的卧室是私有的&#xff0c;也就是说只有你能进去 但是呢&#xff0c;你也可以允许你的好闺蜜好基友进去。 在程序里&#xff0c;有些私有属性 也想让类外特殊的一些…

【物联网】STM32的中断机制不清楚?看这篇文章就足够了

在嵌入式系统中&#xff0c;中断是一种重要的机制&#xff0c;用于处理来自外部设备的异步事件。STM32系列微控制器提供了强大的中断控制器&#xff0c;可以方便地处理各种外部中断和内部中断。本文将详细介绍STM32中断的结构和使用方法。 文章目录 1. 什么叫中断2. 中断优先级…

Jmeter基础篇

1.性能测试指标 【虚拟用户数】&#xff1a;线程用户 【并发数】&#xff1a;指在某一时间&#xff0c;一定数量的虚拟用户同时对系统的某个功能进行交互&#xff0c;一般通过集合点实现 【事务】:事务代表一个完整的功能&#xff0c;一个接口可以是事务&#xff0c;多个接口…

linux——进程间通信——管道

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——进程间通信——管道通信 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;进程间通信&#xff08;InterProcess Communication&…

数据结构与算法系列-二分查找

二分查找 什么是二分查找&#xff1f; 二分查找是一种针对有序集合&#xff0c;每次将要查找的区间缩小一半&#xff0c;直到找到查找元素&#xff0c;或区间被缩小为0。 如何实现二分查找&#xff1f; 实现有3个注意点&#xff1a; 终止条件是 low < high 2.求中点的算…