Decimal separators (comma) lost in numeric cells when OCRing an isolated crop of a table region vs. full-page OCR
Author: textlastigCreated Aug 28, 2026Updated Sep 22, 2026
### System Info / 系統信息
- Backend: MLX (mlx_vlm), model mlx-community/GLM-OCR-bf16
- Served via the SDK's own glmocr server (/glmocr/parse), not vLLM
- Apple Silicon Mac, macOS
- Deterministic decoding configured: temperature: 0.0, top_p: 0.00001, top_k: 1 (per config.yaml)
### Who can help? / 谁可以帮助到您?
_No response_
### Information / 问题信息
- [ ] The official example scripts / 官方的示例脚本
- [x] My own modified scripts / 我自己修改的脚本和任务
### Reproduction / 复现过程
As a workaround for #240 (missing/garbled table footer rows during full-page OCR), we tried re-recognizing just the affected table region: cropping the page to the table's own detected bbox_2d (with modest padding), wrapping it as a single-page PDF, and submitting that alone to /glmocr/parse, e.g.:
from mlx_vlm import load, generate
from mlx_vlm.prompt_utils import apply_chat_template
model, processor = load("mlx-community/GLM-OCR-bf16")
prompt = "Table Recognition:"
formatted_prompt = apply_chat_template(
processor, model.config, prompt, num_images=1)
result = generate(
model,
processor,
formatted_prompt,
image=["./invoice_table_crop_only.png"], # same table, but as an isolated crop instead of the full page
max_tokens=2048,
verbose=True,
)
Steps to reproduce the behavior:
Run OCR on the full page containing the table from #TODO-issue1-number — numeric cells come back with a decimal comma (10,72, 2,300, etc.), as shown there.
Crop the page down to just that table's own detected bbox_2d and run OCR again on the crop alone.
Compare the two outputs — every numeric cell in the crop has lost its decimal separator.
Full-page output for this table (from #TODO-issue1-number, line 1): 10,72, 13,41, 2,300, etc. — with commas.
Isolated-crop output for the identical table:
10,72 → 1072, 2,300 → 2300, and so on for every numeric cell, both in json_result and markdown_result. Note this run did recover the two footer rows from #240 (label and amount both present this time) — but 86,23 came back as 8623, i.e. the same comma loss affecting the rest of the table.
We compared our crop pipeline against the SDK's own internal per-region cropping (glmocr/utils/image_utils.py::crop_image_region, glmocr/pipeline/_workers.py::_flush_layout_batch) and found identical padding (none), identical DPI (200), identical prompt (Table Recognition:), and identical sampling params — so no obvious tunable difference. The one architectural difference we found: /glmocr/parse always runs the full pipeline (layout detection → per-region crop → recognition), so submitting an already-cropped table image causes layout detection to run a second time on an already-tiny, atypical (very dense, no page context) image — something the internal per-region path never does, since there the bbox from a single page-level layout pass is used directly.
This might be related to #228 (crop-based inference reported as generally worse) but that report doesn't mention number formatting specifically, so filing separately in case the mechanism differs.
### Expected behavior / 期待表现
Numeric cells should keep their decimal separator regardless of whether the table is recognized as part of a full page or as an isolated crop — the same 10,72 should not become 1072 just because of how the input image was framed.
Is there a way to submit a region for recognition using a known layout label (e.g. "this is a table") without re-running layout detection on the crop? That would let us bypass this second-pass degradation entirely.
| Datum | GOÄ | Leistung | Anz. | Auslagen | Faktor | Honorar |
| 13.02.24 | 1 | Beratung(persönlich oder telefon.) | 1 | 2300 | 1072 | |
| 6 | UntersuchungOrgansystemAuge/HNO | 1 | 2300 | 1341 | ||
| 1201 | subj.Refraktionsphär.-zylindr.Gl. | 1 | 2300 | 1193 | ||
| 1202 | objektiveRefraktionsbestimmung | 1 | 2300 | 992 | ||
| 1207 | Prüfung./Bestimmung vonMehrstärken-o.Prismenbrille | 1 | 2300 | 938 | ||
| 1242 | Binoc.Unters.d.Augenhintergrundes | 1 | 2300 | 2038 | ||
| 1256 | Applanationstonometrie | 1 | 1800 | 1049 | ||
| SummeHonorarEUR: | 8623 | |||||
| RechnungsbetragEUR: | 8623 |
Source: zai-org/GLM-OCR