引言
近来,涉及到一些公式识别的项目,输入是公式的图像,输出是LaTeX格式的数学公式字符串。
这类项目一般都采用深度学习的方法来做,这就涉及到构造公式LaTeX字符串和对应渲染后图像的数据集。来训练模型。
经过调研,这种数据来源一般有两种,一是人工标注;二是合成。鉴于训练模型所需庞大的数据量,优先考虑合成这种数据。而合成这种数据集时,就需要将公式的LaTeX字符串渲染为公式的图像,如下图所示: 为此,我做了一些调研,寻求可以实现以上这种效果的方案。
方案一:基于LaTeX环境
该方案需要安装LaTeX环境,MacOS下的安装包大概有5.2G左右。
优点是支持所有的LaTeX文档的渲染,缺点是环境太占地了。
如果使用场景涉及到公式的复杂和多样性,则有必要安装这个环境,然后采用python调用渲染。
具体操作文档,大家可以去网上搜索一番,我这里就不再赘述。
方案二:基于KaTeX
KaTeX 是一个快速,易于使用的JavaScript库,用于在Web上进行TeX数学渲染。支持大部分LaTeX语法。
基于KaTeX方案合成训练所用数据集的方案,只是我的构想,可以单独启动一个支持公式渲染的KaTeX的服务,然后python调用这个服务,输入公式LaTeX字符串,返回渲染后的数学公式图像。
值得说明的是,我并没有真正尝试这种方案,但是是具有可行性的,同时我在Github上并没有找到这种方案的项目。
(推荐) 方案三:基于Matplotlib
基于Matlplotib的方案,我是比较倾向这种方案的,不用额外安装LaTeX环境,因为Matplotlib 实现了一个轻量级的 TeX 表达式解析器和布局引擎,Mathtext 是该引擎支持的 Tex 标记的子集。这一部分的详细介绍,可参见官方文档:Writing mathematical expressions
使用例子:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(3, 3), linewidth=1, edgecolor='black')
fig.text(.2, .7, "plain text: alpha > beta")
fig.text(.2, .5, "Mathtext: $\\alpha > \\beta$")
fig.text(.2, .3, r"raw string Mathtext: $\alpha > \beta$")
渲染结果如下:
不需要安装 TeX 即可使用 Mathtext,因为 Matplotlib 附带了 Mathtext 解析器和引擎。 Mathtext 布局引擎是对 Donald Knuth 的 TeX 中布局算法的相当直接的改编。
设想:可以基于matplotlib这个功能,编写一个自动合成开篇所讲的数据集的小工具。输入公式的LaTeX字符串,输出渲染后的数学公式图像。为此,我写了一个demo代码,大概思路是:
flowchart LR
A(公式LaTeX字符串) --> B(Matplotilb渲染得到图像) --> C(裁剪多余部分) --> D(只有公式的图像)
整体流程图如下: 相关代码如下: 借助matplotlib渲染公式部分:
from matplotlib import pyplot as plt
fig = plt.figure(linewidth=1, facecolor="white", layout="tight")
fig.text(0.2, 0.5, r"$c = a^2 + b^2$")
fig.savefig("equation.png")
裁剪多余图像多余部分的代码:
import cv2
import numpy as np
class CropByProject:
"""投影法裁剪"""
def __init__(self, threshold: int = 250):
self.threshold = threshold
def __call__(self, origin_img):
image = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)
# 反色,将大于threshold的值置为0,小于的改为255
retval, img = cv2.threshold(image, self.threshold, 255, cv2.THRESH_BINARY_INV)
# 使文字增长成块
closed = cv2.dilate(img, None, iterations=1)
# 水平投影
x0, x1 = self.get_project_loc(closed, direction="width")
# 竖直投影
y0, y1 = self.get_project_loc(closed, direction="height")
return origin_img[y0:y1, x0:x1]
@staticmethod
def get_project_loc(img, direction):
"""获得裁剪的起始和终点索引位置
Args:
img (ndarray): 二值化后得到的图像
direction (str): 'width/height'
Raises:
ValueError: 不支持的求和方向
Returns:
tuple: 起始索引位置
"""
if direction == "width":
axis = 0
elif direction == "height":
axis = 1
else:
raise ValueError(f"direction {direction} is not supported!")
loc_sum = np.sum(img == 255, axis=axis)
loc_range = np.argwhere(loc_sum > 0)
i0, i1 = loc_range[0][0], loc_range[-1][0]
return i0, i1
if __name__ == "__main__":
cropper = CropByProject()
img_path = "equation.png"
img = cv2.imread(img_path)
result = cropper(img)
cv2.imwrite("res.png", result)
写在最后
目前,公开的公式识别数据集,已经有很多了,包括一些公式识别的比赛以及开源项目中都有涉及,我这里就不再一一列举了,大家可自行寻找。
题外话
感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。
👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
工具都帮大家整理好了,安装就可直接上手!
三、最新Python学习笔记
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、Python视频合集
观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
五、实战案例
纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试宝典
👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)
若有侵权,请联系删除