omr library
Reusable optical-music-recognition API — the CrispEmbed FFI engine plus the pure-Dart parsers, in one import.
This is the OMR pipeline factored out of the crisp_notation omr command so any
Dart program can drive it: the CLI and Flutter desktop (macOS / Windows /
Linux), i.e. anywhere dart:ffi is available. It does not work on the
web (Dart/Flutter web has no dart:ffi, and CrispEmbed's WASM build does not
expose the OMR engines — that would be an upstream change).
Typical use:
import 'package:crisp_notation_cli/omr.dart';
final modelPath = await resolveOmrModel('smt-grandstaff'); // download+cache
final engine = CrispEmbedOmrEngine.load(modelPath); // needs libcrispembed
try {
final tokens = engine.recognizeSync(decodeOmrImage('scan.png'));
final score = switch (omrDialectOf(tokens)) {
OmrDialect.bekern => bekernToGrandStaff(tokens), // → GrandStaff
OmrDialect.semantic => scoreFromSemantic(tokens), // → Score
OmrDialect.lilyNotes => scoreFromLilyNotes(tokens), // → Score
};
// … render / export `score` with crisp_notation_core.
} finally {
engine.dispose();
}
For a full-page scan, split it first with segmentStaffSystems and recognise
each crop. Requires libcrispembed at runtime (see CrispEmbedOmrEngine.load).
Classes
- CrispEmbedOmrEngine
- An OmrEngine backed by CrispEmbed's SMT model through FFI.
- OmrEngine
-
An optical-music-recognition engine: a staff image →
bekerntokens. - OmrImage
-
A pixel buffer for OmrEngine.recognize: row-major
width×height, withchannelsbytes per pixel (1 = gray, 3 = RGB, 4 = RGBA). The engine applies its own grayscale/invert/resize preprocessing.
Enums
- OmrDialect
- Which OMR token dialect an engine returned.
Constants
-
omrModelRegistry
→ const Map<
String, (String, String)> - Known OMR models by short name → (Hugging Face repo, GGUF file). Used by resolveOmrModel to auto-download a model when a name (not a path) is given.
Functions
-
bekernToGrandStaff(
String bekern) → GrandStaff -
bekerntokens → two-staffGrandStaff. -
bekernToKern(
String bekern) → String -
Converts a space-joined
bekerntoken sequence (as returned by the SMT OMR engine) into a Humdrum**kerndocument. -
bekernToScore(
String bekern) → Score -
bekerntokens → single-staffScore(first spine). -
bekernToStaffSystem(
String bekern) → StaffSystem -
bekerntokens →StaffSystem(one staff per spine). -
decodeImageFile(
String path) → Image -
Decodes a PNG/JPEG/BMP image file to an
img.Image. Throws OmrEngineException if it cannot be decoded. -
decodeOmrImage(
String path) → OmrImage - Decodes a PNG/JPEG/BMP image file into an OmrImage (RGBA) for recognition.
-
omrDialectOf(
String tokens) → OmrDialect -
Sniffs which dialect
tokensare, so a caller can pick the right parser without knowing which engine (SMT / TrOMR / Flova) produced them: semantic usesnote-/clef-/…-prefixes;bekernuses<t>/<s>/<b>/**kern; Flova is bare LilyPond notes. -
omrImageOf(
Image image) → OmrImage -
Converts a decoded
imageto an RGBA OmrImage for recognition. -
resolveOmrModel(
String model, {String? cacheDir, void onStatus(String)?}) → Future< String> -
Resolves
modelto a local GGUF path: an existing file path is returned as-is; a registered name (see omrModelRegistry) is downloaded from Hugging Face tocacheDir(default$XDG_CACHE_HOME/crisp_notation/omr) if not already cached, and the cached path returned.onStatusreceives progress lines. -
scoreFromLilyNotes(
String notes) → Score -
Parses a LilyPond simple-notes string (Flova OMR output) into a single-staff
Score. Throws FormatException if no notes/rests are found. -
scoreFromSemantic(
String semantic) → Score -
Parses a TrOMR semantic token stream into a single-staff
Score. -
segmentStaffSystems(
Image image, {double inkFraction = 0.04, int minGapRows = 12, int minBandRows = 16, int padRows = 10}) → List< Image> -
Splits a full-page staff
imageinto individual staff-system crops by horizontal-projection band detection: a row is "ink" if at leastinkFractionof its pixels are dark; maximal ink bands separated by ≥minGapRowsblank rows become separate systems (bands shorter thanminBandRowsare dropped as noise), each padded bypadRows. Returns the whole image (a single element) when it can't find a clean multi-system split — so single-system input is unchanged.
Exceptions / Errors
- OmrEngineException
- Raised when the OMR engine cannot load, initialise, or recognise.