Spaces:
Configuration error
Download README.md from ZainabEman/OCR-Based-Spare-Part-Localization: direct link, hf CLI and curl.
- Browser
- Download file 5.73 kB
-
https://huggingface.co/spaces/ZainabEman/OCR-Based-Spare-Part-Localization/resolve/main/README.md
- Command line
-
hf download hf://spaces/ZainabEman/OCR-Based-Spare-Part-Localization/README.md
-
curl -L -o README.md https://huggingface.co/spaces/ZainabEman/OCR-Based-Spare-Part-Localization/resolve/main/README.md
A newer version of the Streamlit SDK is available: 1.67.0
title: Machine Part Finder
emoji: π
colorFrom: red
colorTo: gray
sdk: streamlit
sdk_version: 1.63.0
python_version: '3.11'
app_file: app.py
app_port: 7860
pinned: false
Machine Part Finder β BQ188 spare-parts catalogue
Type a spare-part number, get the catalogue diagram with the actual machine component outlined in red β not just the printed number.
30642 -> page 34, section 07 "Motor-drive", Schnecke,kpl. / worm,cpl.
red box drawn around the worm gear itself
The source document is 1.pdf, a 55-page catalogue for the BQ188 warp tying
machine. Its exploded-view diagrams label parts with the part number itself,
joined to the component by a thin leader line. Finding the text 30642 is
easy; finding the worm gear it points at is the actual problem this solves.
How it works
Two stages. All the expensive work happens once, offline.
OFFLINE (once, ~10 min) RUNTIME (per search, instant)
1.pdf part number
| parse catalogue tables (real text) | SQLite lookup
| extract diagrams at native resolution | load cached PNG
| OCR the diagrams (RapidOCR) | draw red box in memory
| snap callouts to the known part set | display
| trace leader lines -> component boxes
v
data/catalog.db + data/pages/*.png
The search path never runs OCR, computer vision or PDF parsing β it reads the database and draws rectangles. No network, no LLM, no cloud service is involved at any point, before or after the build.
| Piece | What it does |
|---|---|
spareparts/pdf_loader.py |
Finds the 30 catalogue pages, extracts each diagram |
spareparts/table_parser.py |
Reads the parts tables (real vector text, never OCR) |
spareparts/ocr.py |
OCRs the 30 diagrams, cached to JSON |
spareparts/matcher.py |
Snaps OCR output to the 705 known part numbers |
spareparts/localizer.py |
Traces leader lines to the component (the hard part) |
spareparts/index_db.py |
SQLite schema and queries |
spareparts/lookup.py, overlay.py |
Runtime query and red-box rendering |
app.py |
Streamlit UI |
PSD.md is the project's specification and records what was found in the PDF.
Install
Python 3.11.
pip install -r requirements.txt
Everything runs on CPU and offline. The OCR models ship inside the
rapidocr-onnxruntime wheel; nothing is downloaded at run time.
Build the index
Needed once, before first use, and only again if 1.pdf changes.
python -m spareparts.build_index
Takes about ten minutes and writes data/catalog.db plus data/pages/*.png.
It is safe to re-run: the database is rebuilt from scratch rather than appended
to. OCR results are cached in data/ocr_cache/, so re-running after a change to
the localizer only costs a couple of minutes:
python -m spareparts.build_index --stage annotate # skip re-indexing
python -m spareparts.build_index --stage annotate --debug-images # + overlays
Expected output: 30 catalogue pages, 705 distinct parts, 861 table occurrences, 987 located callouts.
Run the app
streamlit run app.py
Then open http://localhost:8501, type a part number and press Enter.
Example searches
| Search | What you get |
|---|---|
30642 |
One page. Red box on the worm gear, page 34, section 07. |
74506 |
One page, but the part is drawn four times β all four boxed and numbered #1β#4. |
73290 |
Ten pages. An occurrence selector appears; pick which to view. |
99999 |
"Part number not found in the catalogue." |
Input is forgiving: part no. 30642 finds the same part. It is not fuzzy,
though β the digits you type either name a real part or they do not.
Tests
python -m pytest tests -q
Accuracy of the offline stages can be re-measured at any time:
python tools/ocr_report.py # OCR recall, per page
python tools/evaluate.py # localization vs. the hand-checked ground truth
Limitation worth knowing
Localization is deterministic OCR and classical computer vision β binarize, find connected components, trace the leader line from the callout to what it touches. There is no model and nothing is learned from data, so every result can be explained by the geometry that produced it.
That approach has one real limit: where two parts are drawn physically touching, they are a single connected shape and cannot be separated. On the hand-checked set of 87 callouts the tool puts the box on the correct component 90.8% of the time; the misses are almost all parts merged into a larger housing or arm.
Rather than hide this, the app labels every result with how it was obtained:
- Located β the leader line was traced cleanly to the component.
- Assembly β the callout is boxed in the catalogue, so it names a whole group.
- Approximate β the component could not be isolated; the highlight is a conservative area around the leader line's end. Shown with a low confidence.
- Not located β a callout was found but no component could be resolved.
Page 51 is the clearest example: it is a single assembled view where everything touches, so every callout there falls back to "Approximate". The box still lands on the right area, and the app says so instead of implying precision it does not have.
Two other honest caveats:
- The catalogue does not draw every part it lists. When a part is listed on a page but not drawn there, the page is shown without a highlight and the app explains why.
- Occasionally a part is drawn on a page whose own table omits it. Those callouts are still matched against the full catalogue, and flagged.