No camera hardware is on hand yet. This script composites public Open Library cover images onto a synthetic platform background at small/medium/large footprints and drives the real intake pipeline (IntakeSession, Catalogue, capture strategies) end to end, in place of solid-color test frames. Not part of the pytest suite — it fetches over the network and is meant for human-visible verification. |
||
|---|---|---|
| bookmark | ||
| scripts | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| calibrate.py | ||
| CLAUDE.md | ||
| config.example.json | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| run.py | ||
Bookmark
A camera-driven book intake and checkout inventory system, built for Books in Hand, a nonprofit that keeps books out of landfills and in people's hands.
Bookmark replaces manual book logging with a guided, camera-based workflow: a volunteer places a book on a marked platform, the system photographs the front and back, sorts it into a size category for tax/reporting purposes, and later backfills the catalogue with title, author, and ISBN — all running on local hardware, no cloud dependency.
This project is fully open source and is being built and donated as volunteer/client work — it isn't part of any commercial product line.
Status
Phase 1 (intake station) is built, unit-tested, and ready for real-hardware validation. Phase 2 (batch OCR/ISBN backfill) and Phase 3 (checkout station) are planned for later.
| Phase | What it does | Status |
|---|---|---|
| 1 — Intake station | Camera capture, guided front/back flow, deterministic size bucketing, CSV catalogue | Built, unit-tested — pending real-hardware validation |
| 2 — Batch OCR/ISBN backfill | Barcode decode + local vision-LLM fallback to fill in title/author/ISBN | Planned |
| 3 — Checkout station | Track books leaving inventory, reusing the intake identification pipeline | Planned |
How it works (Phase 1)
- A downward-facing webcam looks at a fixed platform with printed nested size-boundary markers (small / medium / large).
- A volunteer centers the book; capture fires automatically or on a button press (configurable).
- The system photographs the front, determines size — deterministically, by checking which physical markers are covered, not by any model inference step — then prompts the volunteer to flip the book and photographs the back.
- Every book gets a row in a CSV catalogue: images, size bucket, and a status that later pipeline stages (OCR backfill, checkout) update.
Full design rationale lives in AGENTS.md (also readable as CLAUDE.md —
same file, symlinked for compatibility with different AI coding tools).
Why this matters for a nonprofit
- No cloud costs, no vendor lock-in. Everything runs on donated hardware; no per-book or per-scan fees.
- Deterministic where it counts. Size-bucket counts feed Books in Hand's year-end tax and 501(c)(3) reporting — that number is computed from physical measurements, not inferred by a model, so it can't drift or hallucinate.
- Volunteer-friendly. The intake flow is designed to be usable by volunteers with no technical background — guided steps, big buttons, no login required.
Development
Requires Python 3.11+.
Setup
-
Create and activate a virtual environment:
python3 -m venv .venv .venv/bin/pip install -e ".[dev]" -
Mount the USB webcam over the capture platform. See the design spec (
circuitforge-plans/books-in-hand/superpowers/specs/2026-07-13-inventory-system-design.md) for physical setup details: nested size-boundary markers, guide box. -
Run calibration once per physical install, with the platform empty:
.venv/bin/python calibrate.py <camera_device_index> reference.jpgThis captures a reference image of the empty platform for marker detection.
-
Copy
config.example.jsontoconfig.jsonand fill in:markers: pixel coordinates (from the reference image)guide_box: capture region boundariestrigger_strategy: one ofmanual,motion_stop, orstable_centered
-
Run the backend:
.venv/bin/python run.py config.json -
Open
http://<machine-ip>:8000in a kiosk-mode browser on the station's monitor.
Running tests
.venv/bin/pytest -v
All tests run without requiring real camera hardware — they use synthetic
NumPy frames and mocked cv2.VideoCapture.
End-to-end smoke test (manual, requires real hardware)
This checklist is for whoever installs this system on real hardware. It verifies that the intake workflow functions end-to-end.
- Boot the station per Setup above with
trigger_strategy: "manual". - Place a book on the platform, click "Capture" — confirm the status
advances to "Front captured — flip it over" and a new row appears in
catalogue.csvwith asize_bucketvalue and populatedfront_wide_path/front_cropped_pathcolumns pointing at real files undercaptures/<book_id>/. - Flip the book, click "Capture" again — confirm status advances to
"Book complete!" and the same row now has
back_wide_path/back_cropped_pathpopulated. - Click "Next Book" — confirm status returns to "Waiting for book..." and
the next capture gets a different
book_id. - Repeat with a small book and a large book — confirm
size_bucketdiffers correctly between them, matching which physical markers each book actually covers. - Switch
trigger_strategytomotion_stopinconfig.json, restart, and confirm placing a book and holding it still triggers capture without pressing the button. - Switch to
stable_centeredand repeat, confirming capture fires once the book is centered and steady in the guide box.
License
MIT — see LICENSE.