# liebharc/homr architecture

> Architecture diagram of the GitHub repository liebharc/homr, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/liebharc/homr
- Repository: https://github.com/liebharc/homr

## Overview

homr converts sheet-music images or PDFs into MusicXML through image segmentation, staff reconstruction, and transformer-based symbol recognition. The README documents the pipeline stages and capabilities; the sampled source confirms the CLI orchestration entry point, inference components, decoder behavior, and web wrapper. Some wiring is documented rather than visible in the partial excerpts, so the graph omits uncertain helper-level relationships.

Main entry points: [`homr/main.py`](https://github.com/liebharc/homr/blob/main/homr/main.py) (CLI orchestrator), [`docker/web/app.py`](https://github.com/liebharc/homr/blob/main/docker/web/app.py) (Web upload API), [`homr/music_xml_generator.py`](https://github.com/liebharc/homr/blob/main/homr/music_xml_generator.py) (MusicXML generation), [`homr/pdf_utils.py`](https://github.com/liebharc/homr/blob/main/homr/pdf_utils.py) (PDF conversion)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["Entry points"]
  node_cli["CLI orchestrator<br/>[main.py]"]
  node_web["Web upload API<br/>[app.py]"]
end

subgraph group_structure["Image structure"]
  node_preprocess["Image preparation<br/>[image_utils.py]"]
  node_pdf["PDF conversion<br/>[pdf_utils.py]"]
  node_segmentation["Segmentation inference"]
  node_boxes["Element boxes<br/>[bounding_boxes.py]"]
  node_staff["Staff detection<br/>[staff_detection.py]"]
  node_anchors["Staff anchors<br/>[staff_regions.py]"]
  node_merge["Staff merging"]
  node_dewarp["Staff dewarping<br/>[staff_dewarping.py]"]
end

subgraph group_recognition["Symbol recognition"]
  node_encoder["Transformer encoder"]
  node_decoder["Symbol decoder"]
  node_vocabulary["Symbol vocabulary<br/>[vocabulary.py]"]
  node_staff_score["Staff-to-score conversion<br/>[staff2score.py]"]
end

subgraph group_output["MusicXML output"]
  node_xml["MusicXML generation"]
  node_result["MusicXML file"]
  node_relieur["Score combining<br/>[relieur.py]"]
end

node_cli_user(("CLI user"))
node_web_user(("Web user"))
node_input["Image or PDF"]
node_consumer(("MusicXML tools"))

node_cli_user -->|"runs"| node_cli
node_cli -->|"reads"| node_input
node_cli -->|"converts PDFs"| node_pdf
node_pdf -->|"provides image"| node_preprocess
node_cli -->|"prepares image"| node_preprocess
node_cli -->|"runs inference"| node_segmentation
node_segmentation -->|"yields regions"| node_boxes
node_cli -->|"detects staffs"| node_staff
node_staff -->|"uses anchors"| node_anchors
node_cli -->|"merges staffs"| node_merge
node_cli -->|"corrects perspective"| node_dewarp
node_cli -->|"encodes staff"| node_encoder
node_encoder -->|"supplies features"| node_decoder
node_decoder -->|"decodes tokens"| node_vocabulary
node_cli -->|"converts symbols"| node_staff_score
node_staff_score -->|"provides score"| node_xml
node_cli -->|"writes output"| node_xml
node_xml -->|"saves"| node_result
node_result -.->|"opens"| node_consumer
node_web_user -->|"uploads score"| node_web
node_web -->|"invokes conversion"| node_cli
node_web -->|"returns file"| node_result
node_cli -.->|"combines inputs"| node_relieur

click node_cli "https://github.com/liebharc/homr/blob/main/homr/main.py"
click node_web "https://github.com/liebharc/homr/blob/main/docker/web/app.py"
click node_preprocess "https://github.com/liebharc/homr/blob/main/homr/image_utils.py"
click node_pdf "https://github.com/liebharc/homr/blob/main/homr/pdf_utils.py"
click node_segmentation "https://github.com/liebharc/homr/blob/main/homr/segmentation/inference_segnet.py"
click node_boxes "https://github.com/liebharc/homr/blob/main/homr/bounding_boxes.py"
click node_staff "https://github.com/liebharc/homr/blob/main/homr/staff_detection.py"
click node_anchors "https://github.com/liebharc/homr/blob/main/homr/staff_regions.py"
click node_merge "https://github.com/liebharc/homr/blob/main/homr/brace_dot_detection.py"
click node_dewarp "https://github.com/liebharc/homr/blob/main/homr/staff_dewarping.py"
click node_encoder "https://github.com/liebharc/homr/blob/main/homr/transformer/encoder_inference.py"
click node_decoder "https://github.com/liebharc/homr/blob/main/homr/transformer/decoder_inference.py"
click node_vocabulary "https://github.com/liebharc/homr/blob/main/homr/transformer/vocabulary.py"
click node_staff_score "https://github.com/liebharc/homr/blob/main/homr/transformer/staff2score.py"
click node_xml "https://github.com/liebharc/homr/blob/main/homr/music_xml_generator.py"
click node_relieur "https://github.com/liebharc/homr/blob/main/homr/relieur.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cli,node_web,node_cli_user,node_web_user toneBlue
class node_preprocess,node_pdf,node_segmentation,node_boxes,node_staff,node_anchors,node_merge,node_dewarp toneAmber
class node_encoder,node_decoder,node_vocabulary,node_staff_score toneMint
class node_xml,node_result,node_relieur toneRose
class node_input,node_consumer toneIndigo
```

## Components

### Entry points

- [CLI orchestrator](https://github.com/liebharc/homr/blob/main/homr/main.py): `homr/main.py`
- [Web upload API](https://github.com/liebharc/homr/blob/main/docker/web/app.py): `docker/web/app.py`

### Image structure

- [Image preparation](https://github.com/liebharc/homr/blob/main/homr/image_utils.py): `homr/image_utils.py`
- [PDF conversion](https://github.com/liebharc/homr/blob/main/homr/pdf_utils.py): `homr/pdf_utils.py`
- [Segmentation inference](https://github.com/liebharc/homr/blob/main/homr/segmentation/inference_segnet.py): `homr/segmentation/inference_segnet.py`
- [Element boxes](https://github.com/liebharc/homr/blob/main/homr/bounding_boxes.py): `homr/bounding_boxes.py`
- [Staff detection](https://github.com/liebharc/homr/blob/main/homr/staff_detection.py): `homr/staff_detection.py`
- [Staff anchors](https://github.com/liebharc/homr/blob/main/homr/staff_regions.py): `homr/staff_regions.py`
- [Staff merging](https://github.com/liebharc/homr/blob/main/homr/brace_dot_detection.py): `homr/brace_dot_detection.py`
- [Staff dewarping](https://github.com/liebharc/homr/blob/main/homr/staff_dewarping.py): `homr/staff_dewarping.py`

### Symbol recognition

- [Transformer encoder](https://github.com/liebharc/homr/blob/main/homr/transformer/encoder_inference.py): `homr/transformer/encoder_inference.py`
- [Symbol decoder](https://github.com/liebharc/homr/blob/main/homr/transformer/decoder_inference.py): `homr/transformer/decoder_inference.py`
- [Symbol vocabulary](https://github.com/liebharc/homr/blob/main/homr/transformer/vocabulary.py): `homr/transformer/vocabulary.py`
- [Staff-to-score conversion](https://github.com/liebharc/homr/blob/main/homr/transformer/staff2score.py): `homr/transformer/staff2score.py`

### MusicXML output

- [MusicXML generation](https://github.com/liebharc/homr/blob/main/homr/music_xml_generator.py): `homr/music_xml_generator.py`
- **MusicXML file**
- [Score combining](https://github.com/liebharc/homr/blob/main/homr/relieur.py): `homr/relieur.py`

### Other components

- **CLI user**
- **Web user**
- **Image or PDF**
- **MusicXML tools**

## Connections

- CLI user → CLI orchestrator: runs
- CLI orchestrator → Image or PDF: reads
- CLI orchestrator → PDF conversion: converts PDFs
- PDF conversion → Image preparation: provides image
- CLI orchestrator → Image preparation: prepares image
- CLI orchestrator → Segmentation inference: runs inference
- Segmentation inference → Element boxes: yields regions
- CLI orchestrator → Staff detection: detects staffs
- Staff detection → Staff anchors: uses anchors
- CLI orchestrator → Staff merging: merges staffs
- CLI orchestrator → Staff dewarping: corrects perspective
- CLI orchestrator → Transformer encoder: encodes staff
- Transformer encoder → Symbol decoder: supplies features
- Symbol decoder → Symbol vocabulary: decodes tokens
- CLI orchestrator → Staff-to-score conversion: converts symbols
- Staff-to-score conversion → MusicXML generation: provides score
- CLI orchestrator → MusicXML generation: writes output
- MusicXML generation → MusicXML file: saves
- MusicXML file → MusicXML tools: opens
- Web user → Web upload API: uploads score
- Web upload API → CLI orchestrator: invokes conversion
- Web upload API → MusicXML file: returns file
- CLI orchestrator → Score combining: combines inputs
