The Problem

Users on Windows need a lightweight, offline OCR tool that can turn images of LaTeX formulas, tables, and mixed Chinese‑English text into editable source. Existing solutions either require a GPU, depend on cloud APIs, or lack a simple desktop UI, making them unsuitable for confidential or low‑spec environments.

What This Does

MixTeX‑Latex‑OCR bundles a CPU‑only inference pipeline with a small PyQt UI. The core OCR logic lives in mixtex_data_gen/gen.py; the desktop front‑end is in mixtexgui/mixtex_ui.py.

  • mixtex_data_gen/gen.py provides the text‑processing chain (remove_non_english_characters, extract_latex_formulas, process_text, remove_symbols, format_text_with_latex) and writes the final LaTeX strings to disk via write_strings_to_files.
  • mixtexgui/mixtex_ui.py implements the UI callbacks that load images, resize them (scale_size), and invoke the inference routine (stream_inference from mixtexgui/examples/mixtex_core.py).
  • mixtexgui/examples/mixtex_core.py houses the model loader (load_model), preprocessing helpers (pad_image, check_repetition), and the actual inference entry point (stream_inference).

All heavy lifting stays in these three files; the remaining scripts (examples/example.py, example_streamlit.py) are thin wrappers for demo purposes.

How It Is Wired

Execution starts at the entry point main in mixtex_data_gen/gen.py:162. main orchestrates a linear pipeline:

  1. Read input – (not shown directly, but main eventually calls write_strings_to_files).
  2. Process text – calls remove_non_english_characters, extract_latex_formulas, process_text, remove_symbols, format_text_with_latex.
  3. Persist resultwrite_strings_to_files creates output directories with os.makedirs and writes the LaTeX strings.

The UI path begins in mixtexgui/mixtex_ui.py. The class MixTeXApp (__init__) constructs the window and registers callbacks. When a user drops an image or clicks “Run”:

  • show_feedback_optionshandle_feedback (4 calls) – displays status messages.
  • add_annotationscale_size (4 calls) – rescales the image for the model.
  • update_annotation_positionscale_size (2 calls) – keeps UI annotations aligned after scaling.
  • update_iconload_scaled_image (2 calls) – loads the raster for display.

scale_size is the hub: invoked from 6 distinct locations, making it the function with the widest blast radius. It ultimately feeds the pre‑processed image to stream_inference in mixtex_core.py, which loads the model (load_model), pads the image (pad_image), checks for duplicate content (check_repetition), and runs the inference graph.

No network calls appear; the only external effect is filesystem I/O (os.makedirs, file writes in write_strings_to_files). The internal call graph contains 38 resolved edges, all confined to the three core modules, so changes to scale_size or load_model ripple through most UI actions.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/MixTeX-Latex-OCR
cd MixTeX-Latex-OCR/mixtexgui

# Create the conda environment (Python 3.10.14)
conda create -n mixtex python=3.10.14
conda activate mixtex

# Install Python dependencies
pip install -r requirements.txt

# Build the executable (optional, for distribution)
pyinstaller mixtex_ui.spec

Running the UI:

# After building, the executable is in ./dist/
./dist/mixtex_ui.exe

For a quick script test, run the demo generator:

python ../mixtex_data_gen/gen.py

No environment variables or external services are required.

Real‑World Use

A research lab processes scanned exam sheets containing handwritten equations and tables. They drop each image onto the MixTeX window; the UI rescales the bitmap (scale_size), runs CPU inference (stream_inference), and writes a .tex file (write_strings_to_files). The lab then compiles the LaTeX batch without ever sending data to the cloud.

Code Health & Issues

  • MEDIUM – Dependabot missing – two manifest files (requirements.txt, mixtexgui/requirements.txt) have no automated update bot.
  • MEDIUM – Deep nestingmixtexgui/mixtex_ui.py and mixtex_data_gen/gen.py reach 8 levels of indentation, reducing readability.
  • MEDIUM – File opened without context managermixtexgui/examples/example.py and example_streamlit.py use plain open().
  • MEDIUM – Duplicated code blocks – identical 6‑line snippets appear in the two example scripts.
  • MEDIUM – Broad exception handlingmixtex_data_gen/gen.py catches all exceptions, potentially hiding errors.
  • MEDIUM – High branching densitymixtex_data_gen/gen.py contains 35 branch points in 124 lines, making future extensions error‑prone.

No CI pipeline, Dockerfile, or lockfile is present; the repository includes a LICENSE but no secret leakage was detected.

The Bottom Line

MixTeX delivers a functional, CPU‑only OCR pipeline with a usable Windows UI, suitable for teams that need offline LaTeX extraction without GPU hardware. The codebase is small but suffers from readability and maintainability issues (deep nesting, broad catches) and lacks automation for dependency updates. Engineers comfortable with Python and PyQt can adopt it quickly, but should refactor the hot‑spot functions (scale_size, stream_inference) before heavy customization.