A Flask-based web application for visualizing OCR bounding boxes on Yale IIIF images. Built to inspect and validate output from dots.ocr processing.
- IIIF Image Integration - Loads images directly from Yale Collections IIIF servers
- Bounding Box Visualization - Overlays OCR-detected regions with color-coded boxes
- Interactive Tooltips - Hover over boxes to see extracted text
- Split View Mode - Side-by-side image and full transcription view
- Resizable Panels - Drag the divider to adjust panel widths
- Large File Support - Handles multi-GB JSONL files (streams to disk, indexes by byte offset)
- Database Mode - Pre-index JSONL to SQLite for instant random access to any record
- Navigation - Arrow keys, click navigation, and jump-to-record for large datasets
- Error Handling - Gracefully displays parse errors while allowing continued navigation
Bounding boxes overlaid on the IIIF image with transcription sidebar:
50/50 layout with full transcription text visible:
Adjust the IIIF image resolution to match your OCR processing settings:
# Clone the repository
git clone https://github.com/project-lux/dots-viewer
cd dots-viewer
# Install dependencies
pip install -r requirements.txt
# Run the app
python app.pyThe app will be available at http://127.0.0.1:5001
- Paste one or more lines of JSONL data into the text area
- Click "View Image" to visualize
- Multiple lines enable navigation between records
- Drag & drop or click to select a
.jsonlfile - Large files (3GB+) are supported - they're streamed to disk and indexed
- Use arrow keys or the jump input to navigate
For very large datasets (1M+ records), you can pre-build a SQLite database for instant random access:
# Build the database from a JSONL file
python build_db.py transcriptions.jsonl
# This creates transcriptions.db in the same directoryThen in the app:
- Click "Database Mode" in the navigation
- Enter the full path to your
.dbfile - Click "Load Database" - navigation to any record is instant
| Control | Description |
|---|---|
| Show Boxes | Toggle bounding box visibility |
| Show Labels | Toggle category labels on boxes |
| Zoom | Adjust image zoom level |
| Max Res | Set IIIF image resolution (see note below) |
| Split View | Toggle 50/50 split layout |
| ← → | Navigate between records |
| Go to... | Jump to specific record number |
The bounding box coordinates depend on the image resolution used during OCR processing.
- Most images: Use
Max Res: 1500(default) - Earlier processed images: Use
Max Res: 2500and click Reload
If bounding boxes appear misaligned, try adjusting the Max Res value to match the resolution used when the images were processed with dots.ocr.
The dots.ocr model internally resizes images to dimensions divisible by 28. The viewer accounts for this by:
- Loading the IIIF image at the specified max resolution
- Calculating the dots.ocr internal dimensions (rounded to nearest 28)
- Scaling bounding box coordinates accordingly
Each line should be a JSON object with these fields:
{
"image_id": "abc123...",
"image_url": "https://collections.library.yale.edu/iiif/2/.../full/full/0/default.jpg",
"lux_id": "https://lux.collections.yale.edu/data/object/...",
"transcription": [
{
"bbox": [x1, y1, x2, y2],
"category": "Text",
"text": "Extracted text content..."
}
]
}| Category | Color |
|---|---|
| Page-header | Purple |
| Title | Green |
| Text | Blue |
| Other | Green |
| Key | Action |
|---|---|
← |
Previous record |
→ |
Next record |
Enter (in jump input) |
Go to record |
- Python 3.8+
- Flask
- Werkzeug
MIT
- dots.ocr - The OCR model used to generate transcriptions
- Yale Digital Collections - IIIF image source
- Yale LUX - Linked data platform



