Translates PDFs and images by overlaying translated text directly onto the original document layout — similar to Google Lens, but fully local.
Runs entirely on your machine — no internet required after setup, no external API calls, no data leaves your PC.
translated_docs/, json/, and markdown/ folders.translated_docs/, json/, and markdown/ folders.<th>, <td>, etc.) from OCR output before translation and rendering.Open_Lens_2.0/
├── readme.md
├── setup.bat ← Run once to install everything (Windows)
├── setup_server.sh ← Run once for Linux server deployment (+ Flash Attention)
├── run.bat ← Run daily to launch the app
├── requirements.txt
├── app.py ← Gradio web UI + pipeline orchestration
├── download_model.py ← Downloads dots.mocr weights into models/
├── test_renderer.py ← Visual test for renderer with mock OCR blocks
├── pipeline/
│ ├── init.py
│ ├── ocr.py ← dots.mocr inference + layout parsing
│ ├── translate.py ← Translation router (M2M-100)
│ ├── translate_m2m.py ← M2M-100 translation backend (100 languages)
│ ├── export.py ← JSON + Markdown export from OCR blocks
│ ├── inpaint.py ← Erase original text from image
│ ├── renderer.py ← Overlay translated text (font recovery, form layout)
│ └── pdf_utils.py ← PDF ↔ image conversion (PyMuPDF @ 150 DPI)
└── models/ ← Auto-created, stores downloaded model weights
setup.batrun.bat to start the app.For production / mass-usage deployment on Linux with NVIDIA GPUs:
chmod +x setup_server.sh
./setup_server.sh
This installs everything including Flash Attention 2 for ~30% faster OCR inference.
Requires: CUDA toolkit, gcc/g++, ninja-build.
Double-click run.bat — the Gradio UI opens in your browser automatically.
| Format | Notes |
|---|---|
| All pages processed, multi-page output | |
| JPG/JPEG | Single image |
| PNG | Single image |
Source (auto-detected): French, Catalan, Spanish, Italian, German, Portuguese, Chinese, Japanese, Korean, Arabic, Russian — plus any other language dots.mocr can read (falls back to majority-language detection).
Target (selectable in UI): 100 languages with M2M-100, including all of the above plus:
Afrikaans, Amharic, Asturian, Azerbaijani, Bashkir, Belarusian, Bengali, Breton, Bosnian, Bulgarian, Cebuano, Czech, Croatian, Danish, Estonian, Finnish, Fulah, Georgian, Greek, Gujarati, Haitian Creole, Hausa, Hebrew, Hindi, Hungarian, Armenian, Icelandic, Igbo, Iloko, Indonesian, Irish, Javanese, Kazakh, Khmer, Kannada, Lao, Latvian, Lithuanian, Luxembourgish, Macedonian, Malagasy, Malay, Malayalam, Marathi, Mongolian, Burmese, Nepali, Occitan, Oriya, Pashto, Persian, Punjabi, Romanian, Scottish Gaelic, Serbian, Sindhi, Sinhala, Slovak, Slovenian, Somali, Albanian, Sundanese, Swahili, Swati, Tagalog, Tamil, Thai, Tswana, Ukrainian, Urdu, Uzbek, Vietnamese, Welsh, Western Frisian, Wolof, Xhosa, Yiddish, Yoruba, Zulu.
Both model sizes support the same 100 language codes.
| Setup | Expected speed |
|---|---|
| NVIDIA GPU + Flash Attn (Linux) | ~30–60 s per page |
| NVIDIA GPU + SDPA (Windows) | ~50–80 s per page |
| CPU only (no GPU) | ~2–5 min per page |
dots.mocr auto-detects your GPU. On CUDA, the model runs in bfloat16 with SDPA attention (or Flash Attention 2 if installed on Linux).
Speed depends heavily on two tunable constants in pipeline/ocr.py:
| Knob | What it does | Trade-off |
|---|---|---|
OCR_MAX_PIXELS | Max image resolution fed to the model | Lower = faster, less detail |
MAX_NEW_TOKENS | Max output tokens per page | Lower = faster, may truncate dense pages |
See the commented boxes in pipeline/ocr.py for detailed guidance.
dots.mocr ships custom model code (trust_remote_code=True) that may conflict with certain transformers versions. The OCR pipeline handles these automatically:
flash_attn. On Windows (or any system without it), a lightweight stub module is injected so the import succeeds. The model uses PyTorch SDPA instead — no functionality is lost.DotsVLProcessor may conflict with Qwen2_5_VLProcessor.__init__ in some transformers versions. The pipeline falls back to building the processor manually with the correct chat template and token IDs.requirements.txt."Python not found" — Re-run the Python installer and tick "Add Python to PATH".
"Model download failed" — Check your internet connection. The model only needs to download once.
"Translation failed" — Check the console for the detected language code. M2M-100 supports 100 languages — if the source language is not in the supported set, the text will be returned as-is.
Blank/white overlay — The inpainting step couldn't sample a background colour. Try a higher-resolution scan.
Wrong source language detected — The heuristic may misidentify short text blocks. A future update will add manual source-language override in the UI.
Expose the translation pipeline as a stateless HTTP API so any frontend (React, Vue, mobile app, etc.) can call it:
POST /api/translate
- Body: multipart file upload + target language
- Response: translated PDF/image bytes (or a job ID for async processing)
GET /api/status/{job_id}
- Returns job progress and download URL when complete
Planned stack: FastAPI with background task queue, optional Redis/Celery for multi-worker scaling.
20 commits
Python
92.2%
Shell
4.2%
Batchfile
3.6%
Translates PDFs and images by overlaying translated text directly onto the original document layout — similar to Google Lens, but fully local.
Runs entirely on your machine — no internet required after setup, no external API calls, no data leaves your PC.
translated_docs/, json/, and markdown/ folders.translated_docs/, json/, and markdown/ folders.<th>, <td>, etc.) from OCR output before translation and rendering.Open_Lens_2.0/
├── readme.md
├── setup.bat ← Run once to install everything (Windows)
├── setup_server.sh ← Run once for Linux server deployment (+ Flash Attention)
├── run.bat ← Run daily to launch the app
├── requirements.txt
├── app.py ← Gradio web UI + pipeline orchestration
├── download_model.py ← Downloads dots.mocr weights into models/
├── test_renderer.py ← Visual test for renderer with mock OCR blocks
├── pipeline/
│ ├── init.py
│ ├── ocr.py ← dots.mocr inference + layout parsing
│ ├── translate.py ← Translation router (M2M-100)
│ ├── translate_m2m.py ← M2M-100 translation backend (100 languages)
│ ├── export.py ← JSON + Markdown export from OCR blocks
│ ├── inpaint.py ← Erase original text from image
│ ├── renderer.py ← Overlay translated text (font recovery, form layout)
│ └── pdf_utils.py ← PDF ↔ image conversion (PyMuPDF @ 150 DPI)
└── models/ ← Auto-created, stores downloaded model weights
setup.batrun.bat to start the app.For production / mass-usage deployment on Linux with NVIDIA GPUs:
chmod +x setup_server.sh
./setup_server.sh
This installs everything including Flash Attention 2 for ~30% faster OCR inference.
Requires: CUDA toolkit, gcc/g++, ninja-build.
Double-click run.bat — the Gradio UI opens in your browser automatically.
| Format | Notes |
|---|---|
| All pages processed, multi-page output | |
| JPG/JPEG | Single image |
| PNG | Single image |
Source (auto-detected): French, Catalan, Spanish, Italian, German, Portuguese, Chinese, Japanese, Korean, Arabic, Russian — plus any other language dots.mocr can read (falls back to majority-language detection).
Target (selectable in UI): 100 languages with M2M-100, including all of the above plus:
Afrikaans, Amharic, Asturian, Azerbaijani, Bashkir, Belarusian, Bengali, Breton, Bosnian, Bulgarian, Cebuano, Czech, Croatian, Danish, Estonian, Finnish, Fulah, Georgian, Greek, Gujarati, Haitian Creole, Hausa, Hebrew, Hindi, Hungarian, Armenian, Icelandic, Igbo, Iloko, Indonesian, Irish, Javanese, Kazakh, Khmer, Kannada, Lao, Latvian, Lithuanian, Luxembourgish, Macedonian, Malagasy, Malay, Malayalam, Marathi, Mongolian, Burmese, Nepali, Occitan, Oriya, Pashto, Persian, Punjabi, Romanian, Scottish Gaelic, Serbian, Sindhi, Sinhala, Slovak, Slovenian, Somali, Albanian, Sundanese, Swahili, Swati, Tagalog, Tamil, Thai, Tswana, Ukrainian, Urdu, Uzbek, Vietnamese, Welsh, Western Frisian, Wolof, Xhosa, Yiddish, Yoruba, Zulu.
Both model sizes support the same 100 language codes.
| Setup | Expected speed |
|---|---|
| NVIDIA GPU + Flash Attn (Linux) | ~30–60 s per page |
| NVIDIA GPU + SDPA (Windows) | ~50–80 s per page |
| CPU only (no GPU) | ~2–5 min per page |
dots.mocr auto-detects your GPU. On CUDA, the model runs in bfloat16 with SDPA attention (or Flash Attention 2 if installed on Linux).
Speed depends heavily on two tunable constants in pipeline/ocr.py:
| Knob | What it does | Trade-off |
|---|---|---|
OCR_MAX_PIXELS | Max image resolution fed to the model | Lower = faster, less detail |
MAX_NEW_TOKENS | Max output tokens per page | Lower = faster, may truncate dense pages |
See the commented boxes in pipeline/ocr.py for detailed guidance.
dots.mocr ships custom model code (trust_remote_code=True) that may conflict with certain transformers versions. The OCR pipeline handles these automatically:
flash_attn. On Windows (or any system without it), a lightweight stub module is injected so the import succeeds. The model uses PyTorch SDPA instead — no functionality is lost.DotsVLProcessor may conflict with Qwen2_5_VLProcessor.__init__ in some transformers versions. The pipeline falls back to building the processor manually with the correct chat template and token IDs.requirements.txt."Python not found" — Re-run the Python installer and tick "Add Python to PATH".
"Model download failed" — Check your internet connection. The model only needs to download once.
"Translation failed" — Check the console for the detected language code. M2M-100 supports 100 languages — if the source language is not in the supported set, the text will be returned as-is.
Blank/white overlay — The inpainting step couldn't sample a background colour. Try a higher-resolution scan.
Wrong source language detected — The heuristic may misidentify short text blocks. A future update will add manual source-language override in the UI.
Expose the translation pipeline as a stateless HTTP API so any frontend (React, Vue, mobile app, etc.) can call it:
POST /api/translate
- Body: multipart file upload + target language
- Response: translated PDF/image bytes (or a job ID for async processing)
GET /api/status/{job_id}
- Returns job progress and download URL when complete
Planned stack: FastAPI with background task queue, optional Redis/Celery for multi-worker scaling.
20 commits
Python
92.2%
Shell
4.2%
Batchfile
3.6%