- YOLOv5 TFLite coin detection with NMS - Blur classifier for image quality gating - Circular contour refinement and cropping - Camera capture and gallery pick Co-authored-by: Cursor <cursoragent@cursor.com>
45 lines
1.2 KiB
Dart
45 lines
1.2 KiB
Dart
import 'dart:math' as math;
|
|
import 'dart:ui';
|
|
|
|
/// Circular capture guide (coin frame).
|
|
class GuideFrame {
|
|
static const double maxDiameterFraction = 0.72;
|
|
static const double centerYFraction = 0.46;
|
|
|
|
static Rect inViewport(Size size) {
|
|
final d = math.min(size.width, size.height) * maxDiameterFraction;
|
|
return Rect.fromCenter(
|
|
center: Offset(size.width / 2, size.height * centerYFraction),
|
|
width: d,
|
|
height: d,
|
|
);
|
|
}
|
|
|
|
static Rect inCoverImage({
|
|
required Size viewport,
|
|
required Size imageSize,
|
|
}) {
|
|
final guide = inViewport(viewport);
|
|
final scale = math.max(
|
|
viewport.width / imageSize.width,
|
|
viewport.height / imageSize.height,
|
|
);
|
|
final dispW = imageSize.width * scale;
|
|
final dispH = imageSize.height * scale;
|
|
final ox = (viewport.width - dispW) / 2;
|
|
final oy = (viewport.height - dispH) / 2;
|
|
|
|
final mapped = Rect.fromLTRB(
|
|
(guide.left - ox) / scale,
|
|
(guide.top - oy) / scale,
|
|
(guide.right - ox) / scale,
|
|
(guide.bottom - oy) / scale,
|
|
);
|
|
return mapped.intersect(
|
|
Rect.fromLTWH(0, 0, imageSize.width, imageSize.height),
|
|
);
|
|
}
|
|
|
|
static Rect inImage(Size imageSize) => inViewport(imageSize);
|
|
}
|