improve parsing 2
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/// One OCR text fragment with pixel bounding box on the receipt image.
|
||||
library;
|
||||
|
||||
class OcrElement {
|
||||
const OcrElement({
|
||||
required this.text,
|
||||
required this.left,
|
||||
required this.top,
|
||||
required this.right,
|
||||
required this.bottom,
|
||||
});
|
||||
|
||||
final String text;
|
||||
final double left;
|
||||
final double top;
|
||||
final double right;
|
||||
final double bottom;
|
||||
|
||||
double get centerX => (left + right) / 2;
|
||||
double get centerY => (top + bottom) / 2;
|
||||
double get height => (bottom - top).abs();
|
||||
double get width => (right - left).abs();
|
||||
}
|
||||
|
||||
/// All positioned elements from one ML Kit recognition pass.
|
||||
class OcrDocument {
|
||||
const OcrDocument({
|
||||
required this.elements,
|
||||
required this.imageWidth,
|
||||
required this.imageHeight,
|
||||
required this.flattenedText,
|
||||
});
|
||||
|
||||
final List<OcrElement> elements;
|
||||
final double imageWidth;
|
||||
final double imageHeight;
|
||||
final String flattenedText;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/// Normalized rectangle (0–1) on the receipt photo for review highlights.
|
||||
library;
|
||||
|
||||
class ReceiptBounds {
|
||||
const ReceiptBounds({
|
||||
required this.left,
|
||||
required this.top,
|
||||
required this.right,
|
||||
required this.bottom,
|
||||
});
|
||||
|
||||
final double left;
|
||||
final double top;
|
||||
final double right;
|
||||
final double bottom;
|
||||
|
||||
bool get isEmpty => right <= left || bottom <= top;
|
||||
|
||||
ReceiptBounds union(ReceiptBounds other) {
|
||||
if (isEmpty) return other;
|
||||
if (other.isEmpty) return this;
|
||||
return ReceiptBounds(
|
||||
left: left < other.left ? left : other.left,
|
||||
top: top < other.top ? top : other.top,
|
||||
right: right > other.right ? right : other.right,
|
||||
bottom: bottom > other.bottom ? bottom : other.bottom,
|
||||
);
|
||||
}
|
||||
|
||||
static ReceiptBounds? merge(Iterable<ReceiptBounds> bounds) {
|
||||
ReceiptBounds? merged;
|
||||
for (final box in bounds) {
|
||||
if (box.isEmpty) continue;
|
||||
merged = merged == null ? box : merged.union(box);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
static ReceiptBounds fromPixelRect({
|
||||
required double left,
|
||||
required double top,
|
||||
required double right,
|
||||
required double bottom,
|
||||
required double imageWidth,
|
||||
required double imageHeight,
|
||||
}) {
|
||||
if (imageWidth <= 0 || imageHeight <= 0) {
|
||||
return const ReceiptBounds(left: 0, top: 0, right: 0, bottom: 0);
|
||||
}
|
||||
return ReceiptBounds(
|
||||
left: left / imageWidth,
|
||||
top: top / imageHeight,
|
||||
right: right / imageWidth,
|
||||
bottom: bottom / imageHeight,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/// One visually reconstructed receipt row from clustered OCR elements.
|
||||
library;
|
||||
|
||||
import 'ocr_element.dart';
|
||||
import 'receipt_bounds.dart';
|
||||
|
||||
enum ReceiptRowKind {
|
||||
skip,
|
||||
quantityModifier,
|
||||
nameOnly,
|
||||
item,
|
||||
discount,
|
||||
grandTotal,
|
||||
totalDiscount,
|
||||
}
|
||||
|
||||
class ReceiptRow {
|
||||
const ReceiptRow({
|
||||
required this.kind,
|
||||
required this.text,
|
||||
required this.nameText,
|
||||
this.price,
|
||||
this.quantity,
|
||||
this.unitPrice,
|
||||
this.lineTotal,
|
||||
this.elements = const [],
|
||||
this.bounds,
|
||||
});
|
||||
|
||||
final ReceiptRowKind kind;
|
||||
final String text;
|
||||
final String nameText;
|
||||
final double? price;
|
||||
final int? quantity;
|
||||
final double? unitPrice;
|
||||
final double? lineTotal;
|
||||
final List<OcrElement> elements;
|
||||
final ReceiptBounds? bounds;
|
||||
}
|
||||
Reference in New Issue
Block a user