Mathpix 是优秀的img2latax工具,对于普通用户来说每月有50-100次免费机会,对于需求量大的用户无法满足需求。有一种方法是调用Mathpix官方的API,每月1000次免费机会。
概述
Mathpix是一款跨平台(Windows、macOS、Linux)的 OCR 工具,它能够识别复杂的数学公式,并将其转换为 LaTeX 语法。 LaTeX 是一个十分强大切流行的排版系统,除了能编写数学公式,还能非常完整的撰写学术论文,并且被国际各大机构接受,但一直以入门难著称。 Mathpix 能够直接截取数学公式的图片,将截图转换为 LaTeX 语法,非常简单方便,并且支持三大主流系统。
- 当前Mathpix收费,无限次识别的Pro账户每个月需要4.99$
- 但是如果调用Mathpix的API的话,每个账户每个月的前 1000 次请求免费;随后的第 1-100 千次,每次 0.004 美元;第 100- 300 千次,每次 0.002 美元。这种收费模式显然比较合理,至少每个月有1000次的免费调用机会。
- 官网链接:https://mathpix.com/
注册账号
- https://accounts.mathpix.com/login
- 注册 MathPix 账号
- 登录账号
创建API
- 选择 OCR API
- 接受一个激活协议
- 使用信用卡激活
- 此处只能使用信用卡
- 卡号填卡号
- 日期填卡上的日期
- CVC是卡背面数字的后三位
- 此处会有1$的消费
- 成功后会获得
App ID
和App Key
调用官方API
- 官方文档 https://docs.mathpix.com
- API的示例https://github.com/Mathpix/api-examples
- 核心调用代码(python):
import os
import requests
env = os.environ
default_headers = {
'app_id': env.get('APP_ID', '你的APP_ID'),
'app_key': env.get('APP_KEY', '你的APP_KEY'),
'Content-type': 'application/json'
}
service = 'https://api.mathpix.com/v3/latex'
...
r = requests.post(service, data=json.dumps(args), headers=headers, timeout=timeout)
return json.loads(r.text)
python 桌面应用
- 我们使用一位大佬的python应用为例
- https://github.com/Joshua-li-yi/img2latex
- 代码中
def grapclipboard(self):
应为def grabclipboard(self):
- 代码中
- 代码如下:
python 代码
代码语言:javascript复制# coding:utf-8
import sys
import os
import base64
import requests
import json
import PyQt5.QtGui
import PyQt5.QtCore
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QWidget, QGridLayout, QLineEdit
from PyQt5.QtCore import Qt
from PIL import ImageGrab
import pyperclip
import matplotlib.pyplot as plt
env = os.environ
default_headers = {
'app_id': env.get('APP_ID', '你的APP_ID'),
'app_key': env.get('APP_KEY', '你的APP_KEY'),
'Content-type': 'application/json'
}
service = 'https://api.mathpix.com/v3/latex'
class Img2Latex(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 800, 700)
self.setWindowTitle('Img2Latex')
# copy latex
self.Latex1copyBtn = QPushButton()
self.Latex2copyBtn = QPushButton()
self.Latex3copyBtn = QPushButton()
# set copy btn icon
self.Latex1copyBtn.setIcon(PyQt5.QtGui.QIcon(r".imgcopy.png"))
self.Latex2copyBtn.setIcon(PyQt5.QtGui.QIcon(r".imgcopy.png"))
self.Latex3copyBtn.setIcon(PyQt5.QtGui.QIcon(r".imgcopy.png"))
# edit latex
self.Latex1EditBtn = QPushButton()
self.Latex2EditBtn = QPushButton()
self.Latex3EditBtn = QPushButton()
# set edit btn icon
self.Latex1EditBtn.setIcon(PyQt5.QtGui.QIcon(r".imgedit.png"))
self.Latex2EditBtn.setIcon(PyQt5.QtGui.QIcon(r".imgedit.png"))
self.Latex3EditBtn.setIcon(PyQt5.QtGui.QIcon(r".imgedit.png"))
# img to latex convert btn
self.img2latexBtn = QPushButton('convert')
# show the picture on clipboard
self.imgLable = QLabel()
# show the formula in latex
self.Latex1Edit = QLineEdit()
self.Latex2Edit = QLineEdit()
self.Latex3Edit = QLineEdit()
self.Latex1Edit.setEnabled(False)
self.Latex2Edit.setEnabled(False)
self.Latex3Edit.setEnabled(False)
# # show the convert latex result
# self.reviewImgLable = QLabel()
# self.reviewImgLable.setStyleSheet("border: 2px solid red")
grid = QGridLayout()
grid.setSpacing(20)
# 排版
grid.addWidget(self.imgLable, 1, 0, 5, 3)
grid.addWidget(self.img2latexBtn,6,0,1,2)
grid.addWidget(self.Latex1Edit, 7, 0)
grid.addWidget(self.Latex1copyBtn, 7, 1)
# grid.addWidget(self.Latex1EditBtn, 7, 2)
grid.addWidget(self.Latex2copyBtn, 8, 1)
grid.addWidget(self.Latex2Edit, 8, 0)
# grid.addWidget(self.Latex2EditBtn, 8, 2)
grid.addWidget(self.Latex3copyBtn, 9, 1)
grid.addWidget(self.Latex3Edit, 9, 0)
# grid.addWidget(self.Latex3EditBtn, 9, 2)
# grid.addWidget(self.reviewImgLable, 10, 0, 4, 3)
self.setLayout(grid)
# sign and slot
# img to latex convert
self.img2latexBtn.clicked.connect(self.convert)
# copy latex
self.Latex1copyBtn.clicked.connect(self.copyLatex1)
self.Latex2copyBtn.clicked.connect(self.copyLatex2)
self.Latex3copyBtn.clicked.connect(self.copyLatex3)
# edit latex
# self.Latex1EditBtn.clicked.connect(self.Latex1EditImg)
# self.Latex1Edit.textChanged.connect(self.Latex1EditImg)
# self.Latex2EditBtn.clicked.connect(self.Latex2EditImg)
# self.Latex2Edit.textChanged.connect(self.Latex2EditImg)
# self.Latex3EditBtn.clicked.connect(self.Latex3EditImg)
# self.Latex3Edit.textChanged.connect(self.Latex3EditImg)
# beautify the window
self.Beautify()
self.show()
def Beautify(self):
self.setWindowOpacity(0.9) # 设置窗口透明度
# self.setAttribute(qtpy.QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明
# self.setWindowFlag(qtpy.QtCore.Qt.FramelessWindowHint) # 隐藏边框
pe = PyQt5.QtGui.QPalette()
self.setAutoFillBackground(True)
# pe.setColor(PyQt5.QtGui.QPalette.Window, Qt.Black) #设置背景色
pe.setColor(PyQt5.QtGui.QPalette.Background, Qt.black)
self.setPalette(pe)
self.imgLable.setStyleSheet(
''' QLabel{
border: 2px solid red;
border-radius:15px;
padding:2px 4px;
background-color:#aaa;
}''')
self.Latex1Edit.setStyleSheet(
'''QLineEdit{
border:1px solid gray;
border-radius:10px;
padding:2px 4px;
background-color:#ddd;
height:35px;
font-color:black;
font-weight:1000;
font-size:24px
}''')
self.Latex2Edit.setStyleSheet(
'''QLineEdit{
border:1px solid gray;
border-radius:10px;
padding:2px 4px;
background-color:#ddd;
height:35px;
font-color:black;
font-weight:1000;
font-size:24px
}''')
self.Latex3Edit.setStyleSheet(
'''QLineEdit{
border:1px solid gray;
border-radius:10px;
padding:2px 4px;
background-color:#ddd;
height:35px;
font-color:black;
font-weight:1000;
font-size:24px
}''')
self.Latex1copyBtn.setStyleSheet(
'''QPushButton{
border:1px solid gray;
border-radius:4px;
padding:5px 5px;
height:35px
}''')
self.Latex2copyBtn.setStyleSheet(
'''QPushButton{
border:1px solid gray;
border-radius:4px;
padding:5px 5px;
height:35px
}''')
self.Latex3copyBtn.setStyleSheet(
'''QPushButton{
border:1px solid gray;
border-radius:4px;
padding:5px 5px;
height:35px
}''')
self.img2latexBtn.setStyleSheet(
'''QPushButton{
border:2px solid gray;
border-radius:10px;
padding:5px 5px;
background-color:#555;
font-size:24px;
font-color:#fff;
font-weight:700;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}''')
#
# Return the base64 encoding of an image with the given filename.
#
def image_uri(self,filename):
image_data = open(filename, "rb").read()
return "data:image/jpg;base64," base64.b64encode(image_data).decode()
# Call the Mathpix service with the given arguments, headers, and timeout.
def latex(self,args, headers=default_headers, timeout=30):
r = requests.post(service,
data=json.dumps(args), headers=headers, timeout=timeout)
return json.loads(r.text)
def convert(self):
self.grapclipboard()
r = self.latex({
'src':self.image_uri(r".imgequa.png"),
'formats': ['latex_simplified']
})
# print(r['latex_simplified'])
latex1 = r['latex_simplified']
# test
# latex1='111'
latex2 = '$' latex1 '$'
latex3 = '$$' latex1 '$$'
self.Latex1Edit.setText(latex1)
self.Latex2Edit.setText(latex2)
self.Latex3Edit.setText(latex3)
def copyLatex1(self):
# get the latex formula
text = self.Latex1Edit.text()
# copy it to clipboard
pyperclip.copy(text)
def copyLatex2(self):
text = self.Latex2Edit.text()
pyperclip.copy(text)
def copyLatex3(self):
text = self.Latex3Edit.text()
pyperclip.copy(text)
#
# 识别剪贴板公式
#
def grabclipboard(self):
im = ImageGrab.grabclipboard()
im.save(r'.imgequa.png', 'PNG')
self.imgLable.setPixmap(PyQt5.QtGui.QPixmap(r'.imgequa.png'))
#
# 为程序添加快捷键
#
# 可以自己定义
def keyPressEvent(self, event):
if (event.key() == Qt.Key_T)and(event.modifiers() == Qt.AltModifier):
self.convert()
if (event.key() == Qt.Key_C)and(event.modifiers() == Qt.AltModifier):
self.copyLatex3()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Img2Latex()
sys.exit(app.exec_())
- 需要将自己的 ID 和 Key 填入代码中
示例效果
参考资料
- https://blog.csdn.net/weixin_44984664/article/details/105242426
- https://geomatlab.com/mathpix-api/