深度学习 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 = config

    def __call__(self, img, dropout):
        """Applies convolutions to the image
        Args:
            img: batch of img, shape = (?, height, width, channels), of type tf.uint8
            tf.uint8 因为 2^8 = 256,所以元素值区间 [0, 255],线性压缩到 [-1, 1] 上就是 img = (img - 128) / 128
        Returns:
            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 -> /2
                out = 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 -> id
                out = 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")
 
                # conv
                out = 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  # 2
    channels = tf.shape(x)[-1]  # 512
    num_timescales = channels // (num_dims * 2)  # 512 // (2*2) = 128
    log_timescale_increment = (
        math.log(float(max_timescale) / float(min_timescale)) /
        (tf.to_float(num_timescales) - 1))  # -0.1 / 127
    inv_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; 1
        length = 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; 256
        postpad = channels - (dim + 1) * 2 * num_timescales  # 512-(1;2)*2*128 = 256; 0
        signal = tf.pad(signal, [[0, 0], [prepad, postpad]])  # [14, 512] 分别在矩阵的上下左右填充0
        for _ in range(1 + dim):  # 1; 2
            signal = tf.expand_dims(signal, 0)
        for _ in range(num_dims - 1 - dim):  # 1, 0
            signal = 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

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

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

相关文章

网络安全,SSL证书必不可少!

网站劫持是一种非常严重的安全威胁,会直接影响用户体验,甚至直接跳转其他网页,造成客户流失。它可以通过许多方式实现,却可以给企业或者个人网站做出不可逆的危害,以下是一些基本的防止措施建议: 1.使用HT…

【博士每天一篇文献-算法】Modular state space of echo state network

阅读时间:2023-11-2 1 介绍 年份:2013 作者:陈卫彪,华南理工大学计算机科学与工程学院, 期刊:Neurocomputing 引用量:17 本文介绍了一种改进回声状态网络(ESN)预测性能的新方法。该…

在全志XR806上移植st7789屏幕驱动

前言 很高兴有机会参加本次极术社区举办的“「免费试用」搭载安谋科技STAR-MC1的全志XR806 Wi-FiBLE 开发板试用活动”。 去年就对全志的mcu芯片感兴趣了,一直没有机会接触,看到本次极术社区提供的全志wifi BLE开发板试用,就马上参加了。板…

手把手教你如何扩展(破解)mybatisplus的sql生成 | 京东云技术团队

mybatisplus 的常用CRUD方法 众所周知,mybatisplus提供了强大的代码生成能力,他默认生成的常用的CRUD方法(例如插入、更新、删除、查询等)的定义,能够帮助我们节省很多体力劳动。 他的BaseMapper中定义了这些常用的C…

gorm的自动化工具gen_已设置图床

gorm的自动化工具gen 官方 https://gorm.io/zh_CN/gen/假设数据库结构如 这里使用gen-tool 安装 go install gorm.io/gen/tools/gentoollatest用法 gentool -hUsage of gentool:-c string配置文件名、默认值 “”、命令行选项的优先级高于配置文件。 -db string指定Driver…

《QT从基础到进阶·十五》用鼠标绘制矩形(QGraphicsView、QPainter、QGraphicsRectItem)

以下是鼠标绘制矩形最全的一种用法,完整源码将会放在最后面。 QT版本:5.15.2 VS版本:2019 1、在界面加载一张图片 界面的搭建选用QGraphicsView,自定义类GraphicsView继承QGraphicsView,在主程序中点击按钮打开 图片&…

Hello World背后的逻辑

一门语言的开发入门,总是抬手就能整出一个「Hello World Demo」。比如下面这样: 显然,熟悉 iOS 开发的同学都知道,上面这个来自 Objective-C。 今天,我们就从这熟悉的代码入手,来一起研究研究「Hello Worl…

verdi如何打开时可以加载配置比如字体

打开tcl使能 找到配置字体的命令 其实其他有需要的文件配置都可以在这里找到对应的指令 存储文件 新建verdi001.tcl文件 输入想要调整的字体以及大小 verdiSetFont -font "Bitstream Vera Sans" -size "18" verdiSetFont -monoFont "Courier&q…

Kafka JNDI 注入分析(CVE-2023-25194)

Apache Kafka Clients Jndi Injection 漏洞描述 Apache Kafka 是一个分布式数据流处理平台,可以实时发布、订阅、存储和处理数据流。Kafka Connect 是一种用于在 kafka 和其他系统之间可扩展、可靠的流式传输数据的工具。攻击者可以利用基于 SASL JAAS 配置和 SAS…

做哪些副业可以日赚一百?对程序员来说简直不要太容易!

日赚一百?对程序员来说简直不要太容易!下面给程序员们推荐一些日赚100的副业: ①外包接单 程序员简单粗暴赚钱的副业之一。 外包接单的类型包括但不限于:软件开发、硬件开发、小程序功能开发、web开发……大到一个系统的开发、…

pip 安装任意软件包报错

现象 使用 pip 命令时提示 查看源码 可以看到是从 pip 包中导入 main失败,点击查看目录 main 文件不见了,判断是文件缺失,重装 pip 即可 # python3 下载 pip curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py # python2 下载…

输入网址到网页显示,期间发生了什么?(收藏篇)

解析url 首先浏览器做的第一步工作就是要对 URL 进行解析,从而生成发送给 Web 服务器的请求信息。对 URL 进行解析之后,浏览器确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。 DNS解析 通过浏览器解析 URL 并…

uniapp使用vur-cli新建项目并打包

新建项目 npm install -g vue/cli vue create -p dcloudio/uni-preset-vue my-project选择默认模板npm run dev:h5 运行 安装sass和uview &#xff08;npm安装失败&#xff09; bug&#xff1a;使用uni.scss中的变量或样式&#xff0c;<style lang"scss"> 必…

亚马逊鲲鹏系统六大优势

亚马逊鲲鹏系统六大优势凭借其独特的能力&#xff0c;完全模拟真实的人类行为。只需几个简单的步骤 就可以自由安排任务&#xff0c;让所有账户随时发挥最大的作用。 1、全自动化操作 可以全自动批量注册买家号、AI智能养号、全自动批量测评&#xff0c;模拟人类的操作行为例…

vue-element-admin 集成框架设置中文语言

首先拉取中文版分支代码 https://github.com/PanJiaChen/vue-element-admin/tree/i18n &#xff08;下载卡的话&#xff0c;下载小羊的压缩包&#xff0c;已上传资源&#xff09; \src\lang\index.js 改完dangdangdang可以啦

CSDN中调整图片和文本样式

1.调整图片比例 插入图片后&#xff0c;觉得图片比例不协调&#xff0c;想改小点。只需要在文件后缀加个参数即可&#xff1a;?pic_center 60x。 NOTE&#xff1a;等号左边一定要加个空格&#xff0c;否则格式不生效 2.修改字体颜色 如上 NOTE&#xff1a;等号左边一定要…

Leo赠书活动-07期 【嵌入式虚拟化技术与应用】文末送书

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

UML与PlantUML简介

UML与PlantUML 1、UML与PlantUML概述2、PlantUML使用 1、UML与PlantUML概述 UML&#xff08;Unified Modeling Language&#xff09;是一种统一建模语言&#xff0c;为面向对象开发系统的产品进行说明、可视化、和编制文档的一种标准语言&#xff0c;独立于任何具体程序设计语言…

什么是伺服电机?Parker派克伺服电机盘点

一、什么是伺服电机&#xff1f; 要准确地定义伺服电机&#xff0c;我们首先需理解其核心特性&#xff1a;反馈与闭环控制。伺服电机凭借这些特性&#xff0c;能精确控制扭矩、速度或位置&#xff0c;即使在零速度下&#xff0c;也能保持足够的扭矩以锁定负载。 伺服电机与其…

RAW图像处理软件Capture One 23 Enterprise mac中文版功能特点

Capture One 23 Enterprise mac是一款专业的图像处理软件&#xff0c;旨在为企业用户提供高效、快速和灵活的工作流程。 Capture One 23 Enterprise mac软件的特点和功能 强大的图像编辑工具&#xff1a;Capture One 23 Enterprise提供了一系列强大的图像编辑工具&#xff0c;…