こんにちは、受験勉強から逃げてきたitouです。
今回はpythonでlatexのOCRをやってみたよ、という話です。
mathlogを見ていると、「この人の記事面白い!自分も記事書こ~、でもこんな式latexに打つのがめんどくさい……」ということありますよね。そんな時、役に立つのがOCRです。自動で数式をlatexにしてくれます!
Optical character recognition(光学文字認識)のことで、画像をテキストに変換するプログラムのこと。
LATEXに変換してくれるソフトとしては mathpix が提供するサービスの mathpixsnip がおすすめです。ただしfree版では月10回までしか使えません。(educational版は月20回、Pro版は月5ドルで5000回) 参考
お金をかけたくない。しかし月10回は少ない。そこでpythonを使いましょう。
pythonの開発環境だけです。
githubの このページ にあるように、LatexOCRモジュールを無料でインストールできます。で、次のコードをコピペしてください。
# -*- coding: utf-8 -*-
from PIL import Image
import PySimpleGUI as sg
from PIL import Image
from pix2tex.cli import LatexOCR
import sys
import os
from PIL import Image
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QTextEdit, QFileDialog, QRadioButton, QVBoxLayout, QWidget, QMessageBox
import threading
import pyocr
import pyocr.builders
class OCRApp(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('簡単OCR')
self.setGeometry(100, 100, 800, 600)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout()
self.file_label = QLabel('読み取るファイル(複数選択可)')
self.layout.addWidget(self.file_label)
self.file_text_edit = QTextEdit()
self.layout.addWidget(self.file_text_edit)
self.browse_button = QPushButton('ファイルを選択', self)
self.browse_button.clicked.connect(self.browse_files)
self.layout.addWidget(self.browse_button)
self.execute_button = QPushButton('読み取り実行', self)
self.execute_button.clicked.connect(self.execute_ocr)
self.layout.addWidget(self.execute_button)
self.output_text_edit = QTextEdit()
self.layout.addWidget(self.output_text_edit)
self.central_widget.setLayout(self.layout)
self.files = []
def browse_files(self):
file_dialog = QFileDialog()
files, _ = file_dialog.getOpenFileNames(self, 'ファイルを選択', '', 'Image Files (*.png *.jpg *.jpeg *.bmp);;All Files (*)')
if files:
self.files.extend(files)
self.file_text_edit.setPlainText('\n'.join(self.files))
def execute_ocr(self):
if not self.files:
return
text = ''
for i, file_path in enumerate(self.files):
if i != 0:
text += '================================================================================================\n'
text += self.scan_file_to_str(file_path)
text += '\n\n'
self.output_text_edit.setPlainText(text)
def scan_file_to_str(self,file_path):
img = Image.open(file_path)
model = LatexOCR()
text = model(img)
return text
実行すると数秒後次のウィンドウがでてきます。
ウィンドウ
ここで「ファイルを選択」をクリックし、変換したい画像ファイルを選択します。そして「読み取り実行」を押すだけです。そこそこ時間がかかります。
例
私の記事の画像
を変換すると
$\begin{array}{r l}{(n+1)^{2}u_{n+1}(x_{0},x_{1},x_{2})|a,b\rangle=(x_{0}n^{2}+x_{0}n+x_{1})u_{n}(x_{0},x_{1},x_{2})t_{a_{1}})}\\ {=(x_{0}n^{2}+x_{0}n_{1})u_{n}(x_{0}^{2},x_{1},{\frac{x_{2}}{m^{2}}})(a,{\frac{b}{m}})\times m^{n+1}}\\ {=(n+1)^{2}u_{n+1}({\frac{x_{0}}{m}},{\frac{x_{1}}{m^{2}}})(x,{\frac{b}{m}})\times m^{n+1}}\end{array}
$
ちょっと数式が変わってますが、誤差の範囲です。
便利ですね!モジュールの作者の@lukas-blecher
lukas-blecher zsh #301さんに感謝します。手書きの文字とかはうまくいかないこともあります。大学生や研究者はみんなmathpixsnipを使っているのでしょうか?mathlogには中高生も多いので、需要はあるかな?