写 抄 作业输入公式虽然有 cdlatex 和 yasnippet 的帮助, 但是还是好累, 尤其是冬天手冻得慌. 于是到网上去找了一圈公式识别的开源库, 然后抄 epc 的 example 糊了一个简单的 OCR 公式识别并插入的东西.
但是现在的问题就是不会写 async 的调用, 卡 Emacs 还是有点不太舒服. (打算去抄 lsp-bridge, 但是有点力不从心 . 或者能有其他的替代也很好. 不过最近赶期末 ddl 可能不会勤修).
以及没有 mac 以外的系统, 所以屏幕截取函数写得很粗暴.
项目地址:
4 个赞
在线的那几个感觉应该都挺厉害的 (没仔细用过), 主要是用 API 的开销有点吃不消 (也没有支付方式就是了
非常感谢分享。
Linux上也可以的运行。
截图工具替换成:
xfce4-screenshooter
或是
gnome-screenshot
不过,在我的linux i3 桌面环境下有些小问题。
- clipman 必须要运行。
- 上面两个工具,把截图送入剪贴版时,非常慢,似乎要2-3秒。
暂时解决方案,把截图放到 python 代码中:
# img = ImageGrab.grabclipboard()
fh, filepath = tempfile.mkstemp(".png")
os.close(fh)
# subprocess.call(["gnome-screenshot", "-a", "-f", filepath])
subprocess.call(["xfce4-screenshooter", "-r", "-s", filepath])
img = Image.open(filepath)
img.load()
os.unlink(filepath)
我看了一下, pix2tex 是有 cli 版本的,为什么要用 py 呢?
照着 mathpix.el 自己搞了个纯 elisp 版本的:
https://github.com/Elilif/.elemacs/blob/devel/lib/pix2tex.el
效果:
3 个赞
有道理, 学习了.
用 py 的原因是为了再做一些图像预处理的工作 (主要是用于黑板板书的拍照).
1 个赞
报错了
Debugger entered--Lisp error: (wrong-type-argument integer-or-marker-p nil)
buffer-substring-no-properties(nil 3771)
(let* ((info (alist-get process pix2tex--process-alist)) (file (car info)) (pos (cdr info)) (beg (search-forward (concat file ": ") (pos-eol) t)) (end (re-search-forward "^$" nil t)) (result (buffer-substring-no-properties beg (1- end)))) (save-current-buffer (set-buffer (marker-buffer pos)) (save-excursion (goto-char pos) (insert result))) (delete-file file) (let* ((p (assq process pix2tex--process-alist))) (progn (if p (setq pix2tex--process-alist (delq p pix2tex--process-alist))) nil)) (kill-buffer proc-buf))
(save-current-buffer (set-buffer proc-buf) (goto-char (point-min)) (let* ((info (alist-get process pix2tex--process-alist)) (file (car info)) (pos (cdr info)) (beg (search-forward (concat file ": ") (pos-eol) t)) (end (re-search-forward "^$" nil t)) (result (buffer-substring-no-properties beg (1- end)))) (save-current-buffer (set-buffer (marker-buffer pos)) (save-excursion (goto-char pos) (insert result))) (delete-file file) (let* ((p (assq process pix2tex--process-alist))) (progn (if p (setq pix2tex--process-alist (delq p pix2tex--process-alist))) nil)) (kill-buffer proc-buf)))
(progn (save-current-buffer (set-buffer proc-buf) (goto-char (point-min)) (let* ((info (alist-get process pix2tex--process-alist)) (file (car info)) (pos (cdr info)) (beg (search-forward (concat file ": ") (pos-eol) t)) (end (re-search-forward "^$" nil t)) (result (buffer-substring-no-properties beg (1- end)))) (save-current-buffer (set-buffer (marker-buffer pos)) (save-excursion (goto-char pos) (insert result))) (delete-file file) (let* ((p (assq process pix2tex--process-alist))) (progn (if p (setq pix2tex--process-alist (delq p pix2tex--process-alist))) nil)) (kill-buffer proc-buf))))
(if (eq (process-status process) 'exit) (progn (save-current-buffer (set-buffer proc-buf) (goto-char (point-min)) (let* ((info (alist-get process pix2tex--process-alist)) (file (car info)) (pos (cdr info)) (beg (search-forward (concat file ": ") (pos-eol) t)) (end (re-search-forward "^$" nil t)) (result (buffer-substring-no-properties beg (1- end)))) (save-current-buffer (set-buffer (marker-buffer pos)) (save-excursion (goto-char pos) (insert result))) (delete-file file) (let* ((p (assq process pix2tex--process-alist))) (progn (if p (setq pix2tex--process-alist ...)) nil)) (kill-buffer proc-buf)))))
(let ((proc-buf (process-buffer process))) (if (eq (process-status process) 'exit) (progn (save-current-buffer (set-buffer proc-buf) (goto-char (point-min)) (let* ((info (alist-get process pix2tex--process-alist)) (file (car info)) (pos (cdr info)) (beg (search-forward ... ... t)) (end (re-search-forward "^$" nil t)) (result (buffer-substring-no-properties beg ...))) (save-current-buffer (set-buffer (marker-buffer pos)) (save-excursion (goto-char pos) (insert result))) (delete-file file) (let* ((p ...)) (progn (if p ...) nil)) (kill-buffer proc-buf))))))
pix2tex--sentinel(#<process pix2tex> "exited abnormally with code 1\n")
这是 pix2tex 异常退出导致的,我在 Linux 上是没问题的,不清楚 mac 上情况。
另外我这是自己写着玩玩的,只考虑自己用的情况,代码仅供参考。
真要用还得看 lz 的包。
Weiss
14
我也试用了下,用的是 LaTeX-OCR 提供的 Docker API 的方式调用的,安装起来比较方便,下面是代码,有兴趣的人可以参考:
(defun weiss-org--parse-latex-image-and-insert (img-path on-success &optional server port)
"DOCSTRING"
(let ((server (or server "http://localhost"))
(port (or port "8502")))
(request (format "%s:%s/predict/" server port)
:type "POST"
:files `(("file" . ,img-path))
:parser 'buffer-string
:success (cl-function (lambda (&key data &allow-other-keys)
(when data (funcall on-success data)
)))
:error
(cl-function (lambda (&rest args &key error-thrown &allow-other-keys)
(message "Got error: %S" error-thrown))))
))
另外,因为用了 request 库,async 是天然支持的。
不过和 mathpix 比了下,效果不太行啊……尤其是多行带 aligned 的,下面是对比
LaTeX-OCR
\begin{array}{c}{{\nabla_{\mathrm{w}}{\cal L}(\bar{\bf w}_{\mathrm{MAP}}\mid{\bf y})=\sigma_{y}^{-2}({\bf X}{\bf X}^{T}\bar{\bf w}_{\mathrm{MAP}}-{\bf X}{\bf y})+\sigma_{w}^{-2}\bar{\bf w}_{\mathrm{MAP}}\stackrel{\prime}{=}{\bf0}}}\\ {{\qquad(\sigma_{y}^{-2}{\bf X}{\bf X}^{T}+\sigma_{w}^{-2}I)\bar{\bf w}_{\mathrm{MAP}}=\sigma_{y}^{-2}{\bf X}{\bf X}^{T}+\sigma_{w}^{-2}I)\bar{\bf w}_{\mathrm{MAP}}=({\bf X}{\bf X}^{T}+\sigma_{y}^{2}\sigma_{w}^{-2}I)^{-1}{\bf X}_{\bf y}}}\\ {{\bf w}}}\end{array}
Mathpix:
\begin{aligned}
\nabla_{\mathbf{w}} L\left(\hat{\mathbf{w}}_{\mathrm{MAP}} \mid \mathbf{y}\right)=\sigma_y^{-2}\left(\mathbf{X} \mathbf{X}^T \hat{\mathbf{w}}_{\mathrm{MAP}}-\mathbf{X} \mathbf{y}\right)+\sigma_w^{-2} \hat{\mathbf{w}}_{\mathrm{MAP}} & \stackrel{!}{=} \mathbf{0} \\
\left(\sigma_y^{-2} \mathbf{X} \mathbf{X}^T+\sigma_w^{-2} I\right) \hat{\mathbf{w}}_{\mathrm{MAP}} & =\sigma_y^{-2} \mathbf{X} \mathbf{y} \\
\hat{\mathbf{w}}_{\mathrm{MAP}} & =\sigma_y^{-2}\left(\sigma_y^{-2} \mathbf{X X}^T+\sigma_w^{-2} I\right)^{-1} \mathbf{X} \mathbf{y} \\
\hat{\mathbf{w}}_{\mathrm{MAP}} & =\left(\mathbf{X X}^T+\sigma_y^2 \sigma_w^{-2} I\right)^{-1} \mathbf{X} \mathbf{y}
\end{aligned}
感觉确实得买个 Mathpix 的 API 了,以我这使用量,估计初始的 20 刀就能用一辈子了