Files
2026-09-02 13:38:47 +02:00

82 lines
2.3 KiB
Dart

/// Extract positioned OCR elements from ML Kit structured output.
library;
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import '../models/ocr_element.dart';
class ReceiptOcr {
ReceiptOcr._();
/// Reads blocks → lines → elements. Falls back to line-level boxes when a
/// line has no element children.
static OcrDocument fromRecognizedText(
RecognizedText recognized, {
required double imageWidth,
required double imageHeight,
}) {
final elements = <OcrElement>[];
final lines = <OcrLine>[];
var maxRight = 0.0;
var maxBottom = 0.0;
for (final block in recognized.blocks) {
for (final line in block.lines) {
final lineElements = <OcrElement>[];
if (line.elements.isNotEmpty) {
for (final element in line.elements) {
final box = element.boundingBox;
lineElements.add(
OcrElement(
text: element.text,
left: box.left,
top: box.top,
right: box.right,
bottom: box.bottom,
),
);
if (box.right > maxRight) maxRight = box.right;
if (box.bottom > maxBottom) maxBottom = box.bottom;
}
} else {
final box = line.boundingBox;
lineElements.add(
OcrElement(
text: line.text,
left: box.left,
top: box.top,
right: box.right,
bottom: box.bottom,
),
);
if (box.right > maxRight) maxRight = box.right;
if (box.bottom > maxBottom) maxBottom = box.bottom;
}
elements.addAll(lineElements);
final box = line.boundingBox;
lines.add(
OcrLine(
text: line.text,
elements: lineElements,
left: box.left,
top: box.top,
right: box.right,
bottom: box.bottom,
),
);
}
}
final width = imageWidth > 0 ? imageWidth : maxRight;
final height = imageHeight > 0 ? imageHeight : maxBottom;
return OcrDocument(
elements: elements,
lines: lines,
imageWidth: width,
imageHeight: height,
flattenedText: recognized.text.trim(),
);
}
}