From e7ae9c31f14f330b24abb64ab4bc5e6b38ced1ea Mon Sep 17 00:00:00 2001 From: Wu Zhenyu Date: Tue, 20 Sep 2022 11:29:13 +0800 Subject: [PATCH 1/8] Fix `--file` and support expanding `~` Fix #176 --- pix2tex/__main__.py | 4 +-- pix2tex/cli.py | 63 ++++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/pix2tex/__main__.py b/pix2tex/__main__.py index 4bd6746..611db56 100755 --- a/pix2tex/__main__.py +++ b/pix2tex/__main__.py @@ -10,18 +10,18 @@ def main(): parser.add_argument('--no-resize', action='store_true', help='Resize the image beforehand') parser.add_argument('-s', '--show', action='store_true', help='Show the rendered predicted latex code (cli only)') - parser.add_argument('-f', '--file', type=str, default=None, help='Predict LaTeX code from image file instead of clipboard (cli only)') parser.add_argument('-k', '--katex', action='store_true', help='Render the latex code in the browser (cli only)') parser.add_argument('--gui', action='store_true', help='Use GUI (gui only)') + parser.add_argument('file', nargs='*', type=str, default=None, help='Predict LaTeX code from image file instead of clipboard (cli only)') arguments = parser.parse_args() import os import sys name = os.path.split(sys.argv[0])[-1] - if arguments.gui or arguments.gnome or name in ['pix2tex_gui', 'latexocr']: + if arguments.gui or name in ['pix2tex_gui', 'latexocr']: from .gui import main else: from .cli import main diff --git a/pix2tex/cli.py b/pix2tex/cli.py index 168c9a6..f590896 100644 --- a/pix2tex/cli.py +++ b/pix2tex/cli.py @@ -105,9 +105,9 @@ def __call__(self, img=None, resize=True) -> str: img = None if img is None: if self.last_pic is None: - print('Provide an image.') return '' else: + print('\nLast image is: ', end='') img = self.last_pic.copy() else: self.last_pic = img.copy() @@ -177,6 +177,23 @@ def output_prediction(pred, args): webbrowser.open(url) +def predict(model, file, arguments): + with suppress(KeyboardInterrupt): + img = None + if file: + try: + img = Image.open(os.path.expanduser(file)) + except Exception as e: + print(e, end='') + else: + try: + img = ImageGrab.grabclipboard() + except NotImplementedError as e: + print(e, end='') + pred = model(img) + output_prediction(pred, arguments) + + def main(arguments): path = user_data_dir('pix2tex') os.makedirs(path, exist_ok=True) @@ -187,9 +204,18 @@ def main(arguments): with suppress(OSError): readline.read_history_file(history_file) atexit.register(readline.write_history_file, history_file) + files = list(map(lambda file: os.path.realpath(file), arguments.file)) with in_model_path(): model = LatexOCR(arguments) - file = None + if files: + for file in files: + print(file + ': ', end='') + predict(model, file, arguments) + model.last_pic = None + with suppress(NameError): + readline.add_history(file) + exit() + pat = re.compile(r't=([\.\d]+)') while True: try: instructions = input('Predict LaTeX code for image ("?"/"h" for help). ') @@ -199,8 +225,9 @@ def main(arguments): continue except EOFError: break - possible_file = instructions.strip() - ins = possible_file.lower() + file = instructions.strip() + ins = file.lower() + t = pat.match(ins) if ins == 'x': break elif ins in ['?', 'h', 'help']: @@ -231,26 +258,10 @@ def main(arguments): setattr(arguments, ins, not getattr(arguments, ins, False)) print('set %s to %s' % (ins, getattr(arguments, ins))) continue - elif os.path.isfile(os.path.realpath(possible_file)): - file = possible_file - else: - t = re.match(r't=([\.\d]+)', ins) - if t is not None: - t = t.groups()[0] - model.args.temperature = float(t)+1e-8 - print('new temperature: T=%.3f' % model.args.temperature) - continue - try: - img = None - if file: - img = Image.open(file) - else: - try: - img = ImageGrab.grabclipboard() - except: - pass - pred = model(img) - output_prediction(pred, arguments) - except KeyboardInterrupt: - pass + elif t is not None: + t = t.groups()[0] + model.args.temperature = float(t)+1e-8 + print('new temperature: T=%.3f' % model.args.temperature) + continue + predict(model, file, arguments) file = None From 7a7f669daabbd884bd4bc6954b58e982abd0cdcf Mon Sep 17 00:00:00 2001 From: Wu Zhenyu Date: Thu, 22 Sep 2022 23:25:28 +0800 Subject: [PATCH 2/8] Refactor code --- pix2tex/cli.py | 61 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/pix2tex/cli.py b/pix2tex/cli.py index f590896..57867f6 100644 --- a/pix2tex/cli.py +++ b/pix2tex/cli.py @@ -3,8 +3,9 @@ from PIL import ImageGrab from PIL import Image import os +from pathlib import Path import sys -from typing import Tuple +from typing import List, Optional, Tuple import atexit from contextlib import suppress import logging @@ -178,21 +179,34 @@ def output_prediction(pred, args): def predict(model, file, arguments): - with suppress(KeyboardInterrupt): - img = None - if file: - try: - img = Image.open(os.path.expanduser(file)) - except Exception as e: - print(e, end='') - else: - try: - img = ImageGrab.grabclipboard() - except NotImplementedError as e: - print(e, end='') - pred = model(img) - output_prediction(pred, arguments) + img = None + if file: + try: + img = Image.open(os.path.expanduser(file)) + except Exception as e: + print(e, end='') + else: + try: + img = ImageGrab.grabclipboard() + except NotImplementedError as e: + print(e, end='') + pred = model(img) + output_prediction(pred, arguments) +def check_file_path(paths:List[Path], wdir:Optional[Path]=None)->List[str]: + files = [] + for path in paths: + if type(path)==str: + if path=='': + continue + path=Path(path) + pathsi = ([path] if wdir is None else [path, wdir/path]) + for p in pathsi: + if p.exists(): + files.append(str(p.resolve())) + elif '*' in path.name: + files.extend([str(pi.resolve()) for pi in p.parent.glob(p.name)]) + return list(set(files)) def main(arguments): path = user_data_dir('pix2tex') @@ -204,11 +218,12 @@ def main(arguments): with suppress(OSError): readline.read_history_file(history_file) atexit.register(readline.write_history_file, history_file) - files = list(map(lambda file: os.path.realpath(file), arguments.file)) + files = check_file_path(arguments.file) + wdir = Path(os.getcwd()) with in_model_path(): model = LatexOCR(arguments) if files: - for file in files: + for file in check_file_path(arguments.file, wdir): print(file + ': ', end='') predict(model, file, arguments) model.last_pic = None @@ -218,7 +233,7 @@ def main(arguments): pat = re.compile(r't=([\.\d]+)') while True: try: - instructions = input('Predict LaTeX code for image ("?"/"h" for help). ') + instructions = input('Predict LaTeX code for image ("h" for help). ') except KeyboardInterrupt: # TODO: make the last line gray print("") @@ -263,5 +278,13 @@ def main(arguments): model.args.temperature = float(t)+1e-8 print('new temperature: T=%.3f' % model.args.temperature) continue - predict(model, file, arguments) + files = check_file_path(file.split(' '), wdir) + with suppress(KeyboardInterrupt): + if files: + for file in files: + if len(files)>1: + print(file + ': ', end='') + predict(model, file, arguments) + else: + predict(model, file, arguments) file = None From 1a109bcc19e7623c436e2fabd93de98704a7ef03 Mon Sep 17 00:00:00 2001 From: Lukas Blecher Date: Thu, 22 Sep 2022 21:32:32 +0200 Subject: [PATCH 3/8] New version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index aeb8e19..19fc190 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ setuptools.setup( name='pix2tex', - version='0.0.27', + version='0.0.28', description='pix2tex: Using a ViT to convert images of equations into LaTeX code.', long_description=long_description, long_description_content_type='text/markdown', From c502efd280571c0920af51be372e6bb9443696d9 Mon Sep 17 00:00:00 2001 From: Frank-Eneer <91851558+FrankFrank9@users.noreply.github.com> Date: Sat, 24 Sep 2022 20:49:04 +0200 Subject: [PATCH 4/8] Solve Retina display issues Initially x1,y1,x2,y2 coordinates in pixel where multiplied by 2 on retina displays but when grabbing you divide by 2 again. This does not solve the issue which is related only to grab where only the box captured must be scaled. Hence the proposed change solve the issue and you can verify with img.show() to check the part of the screen captured --- pix2tex/gui.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pix2tex/gui.py b/pix2tex/gui.py index 3718acf..d25cfd7 100644 --- a/pix2tex/gui.py +++ b/pix2tex/gui.py @@ -276,10 +276,10 @@ def mouseReleaseEvent(self, event): # account for retina display. #TODO how to check if device is actually using retina display factor = 2 if sys.platform == "darwin" else 1 - x1 = int(min(startPos[0], endPos[0])*factor) - y1 = int(min(startPos[1], endPos[1])*factor) - x2 = int(max(startPos[0], endPos[0])*factor) - y2 = int(max(startPos[1], endPos[1])*factor) + x1 = int(min(startPos[0], endPos[0])) + y1 = int(min(startPos[1], endPos[1])) + x2 = int(max(startPos[0], endPos[0])) + y2 = int(max(startPos[1], endPos[1])) self.repaint() QApplication.processEvents() @@ -296,6 +296,9 @@ def mouseReleaseEvent(self, event): self.begin = QtCore.QPoint() self.end = QtCore.QPoint() self.parent.returnSnip(img) + + + img.show() #this line is used only to check what part of the screen is captured. It can be deleted later def main(arguments): From b415d97bca27ef2b1b094477c80dff81ef82f3fd Mon Sep 17 00:00:00 2001 From: Frank-Eneer <91851558+FrankFrank9@users.noreply.github.com> Date: Sat, 24 Sep 2022 20:59:40 +0200 Subject: [PATCH 5/8] Update button on MacOs On MacOS screenshot shortcut is Option+S, adjusted the text displayed in the button. --- pix2tex/gui.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pix2tex/gui.py b/pix2tex/gui.py index 3718acf..c3bcd01 100644 --- a/pix2tex/gui.py +++ b/pix2tex/gui.py @@ -58,11 +58,19 @@ def initUI(self): self.tempField.setSingleStep(0.1) # Create snip button - self.snipButton = QPushButton('Snip [Alt+S]', self) - self.snipButton.clicked.connect(self.onClick) + if sys.platform == "darwin": + self.snipButton = QPushButton('Snip [Option+S]', self) + self.snipButton.clicked.connect(self.onClick) + else: + self.snipButton = QPushButton('Snip [Alt+S]', self) + self.snipButton.clicked.connect(self.onClick) - self.shortcut = QShortcut(QKeySequence("Alt+S"), self) - self.shortcut.activated.connect(self.onClick) + if sys.platform == "darwin": + self.shortcut = QShortcut(QKeySequence("Alt+S"), self) + self.shortcut.activated.connect(self.onClick) + else: + self.shortcut = QShortcut(QKeySequence("Alt+S"), self) + self.shortcut.activated.connect(self.onClick) # Create retry button self.retryButton = QPushButton('Retry', self) From b2b0ef7805dfc472e23cba4ac1352abe88b80e7f Mon Sep 17 00:00:00 2001 From: Frank-Eneer <91851558+FrankFrank9@users.noreply.github.com> Date: Sat, 24 Sep 2022 21:10:44 +0200 Subject: [PATCH 6/8] Update Snip Button 2nd commit Fixed text display few lines after 1st commit as well --- pix2tex/gui.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pix2tex/gui.py b/pix2tex/gui.py index c3bcd01..c0609ed 100644 --- a/pix2tex/gui.py +++ b/pix2tex/gui.py @@ -102,7 +102,10 @@ def toggleProcessing(self, value=None): text = 'Interrupt' func = self.interrupt else: - text = 'Snip [Alt+S]' + if sys.platform == "darwin": + text = 'Snip [Option+S]' + else: + text = 'Snip [Alt+S]' func = self.onClick self.retryButton.setEnabled(True) self.shortcut.setEnabled(not self.isProcessing) From 575a82e1c21e0d1fbcdf8d48da6f239f06a57567 Mon Sep 17 00:00:00 2001 From: Frank-Eneer <91851558+FrankFrank9@users.noreply.github.com> Date: Sun, 25 Sep 2022 18:06:13 +0200 Subject: [PATCH 7/8] Update gui.py deleted img.show() --- pix2tex/gui.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pix2tex/gui.py b/pix2tex/gui.py index d25cfd7..ae8bc91 100644 --- a/pix2tex/gui.py +++ b/pix2tex/gui.py @@ -296,10 +296,6 @@ def mouseReleaseEvent(self, event): self.begin = QtCore.QPoint() self.end = QtCore.QPoint() self.parent.returnSnip(img) - - - img.show() #this line is used only to check what part of the screen is captured. It can be deleted later - def main(arguments): with in_model_path(): From 930428c601e03d03ac19bda49eeec95bda1cf73f Mon Sep 17 00:00:00 2001 From: Frank-Eneer <91851558+FrankFrank9@users.noreply.github.com> Date: Sun, 25 Sep 2022 18:09:33 +0200 Subject: [PATCH 8/8] Update gui.py Corrected if else statement --- pix2tex/gui.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pix2tex/gui.py b/pix2tex/gui.py index c0609ed..8f5177b 100644 --- a/pix2tex/gui.py +++ b/pix2tex/gui.py @@ -65,12 +65,8 @@ def initUI(self): self.snipButton = QPushButton('Snip [Alt+S]', self) self.snipButton.clicked.connect(self.onClick) - if sys.platform == "darwin": - self.shortcut = QShortcut(QKeySequence("Alt+S"), self) - self.shortcut.activated.connect(self.onClick) - else: - self.shortcut = QShortcut(QKeySequence("Alt+S"), self) - self.shortcut.activated.connect(self.onClick) + self.shortcut = QShortcut(QKeySequence("Alt+S"), self) + self.shortcut.activated.connect(self.onClick) # Create retry button self.retryButton = QPushButton('Retry', self)