本文最后更新于:2024年1月14日 晚上

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/

注册账号

创建API

  • 选择 OCR API

  • 接受一个激活协议
  • 使用信用卡激活

  • 此处只能使用信用卡

    • 卡号填卡号
    • 日期填卡上的日期
    • CVC是卡背面数字的后三位
  • 此处会有1$的消费

  • 成功后会获得 App IDApp Key

调用官方API

  • 官方文档 https://docs.mathpix.com
  • API的示例https://github.com/Mathpix/api-examples
  • 核心调用代码(python):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# 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".\img\copy.png"))
self.Latex2copyBtn.setIcon(PyQt5.QtGui.QIcon(r".\img\copy.png"))
self.Latex3copyBtn.setIcon(PyQt5.QtGui.QIcon(r".\img\copy.png"))

# edit latex
self.Latex1EditBtn = QPushButton()
self.Latex2EditBtn = QPushButton()
self.Latex3EditBtn = QPushButton()
# set edit btn icon
self.Latex1EditBtn.setIcon(PyQt5.QtGui.QIcon(r".\img\edit.png"))
self.Latex2EditBtn.setIcon(PyQt5.QtGui.QIcon(r".\img\edit.png"))
self.Latex3EditBtn.setIcon(PyQt5.QtGui.QIcon(r".\img\edit.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".\img\equa.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'.\img\equa.png', 'PNG')
self.imgLable.setPixmap(PyQt5.QtGui.QPixmap(r'.\img\equa.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://www.zywvvd.com/notes/tools/mathpix/math-pix-api-usage/math-pix-api-usage/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

调用 Mathpix AIP 实现每月1000次免费识别
https://www.zywvvd.com/notes/tools/mathpix/math-pix-api-usage/math-pix-api-usage/
作者
Yiwei Zhang
发布于
2021年4月7日
许可协议