|
|
@@ -28,8 +28,11 @@ class _LiveAnalysisScreenState extends State<LiveAnalysisScreen> {
|
|
|
|
|
|
// Detection Lock Logic
|
|
|
bool _isLocked = false;
|
|
|
- static const double _lockThreshold = 0.75;
|
|
|
- static const int _frameThrottle = 10; // Process every 10th frame
|
|
|
+ static const double _lockThreshold = 0.60;
|
|
|
+ static const int _frameThrottle = 2; // Check frames more frequently
|
|
|
+
|
|
|
+ int _consecutiveDetections = 0;
|
|
|
+ static const int _requiredConsecutive = 3; // Number of frames to hold
|
|
|
|
|
|
@override
|
|
|
void initState() {
|
|
|
@@ -78,15 +81,23 @@ class _LiveAnalysisScreenState extends State<LiveAnalysisScreen> {
|
|
|
try {
|
|
|
final detections = await _tfliteService.runInferenceOnStream(image);
|
|
|
|
|
|
- bool locked = false;
|
|
|
+ bool currentFrameHasFruit = false;
|
|
|
if (detections.isNotEmpty) {
|
|
|
- locked = detections.any((d) => d.confidence > _lockThreshold);
|
|
|
+ currentFrameHasFruit = detections.any((d) => d.confidence > _lockThreshold);
|
|
|
}
|
|
|
|
|
|
+ if (currentFrameHasFruit) {
|
|
|
+ _consecutiveDetections++;
|
|
|
+ } else {
|
|
|
+ _consecutiveDetections--; // Just drop by one, don't kill the whole lock
|
|
|
+ }
|
|
|
+
|
|
|
+ _consecutiveDetections = _consecutiveDetections.clamp(0, _requiredConsecutive);
|
|
|
+
|
|
|
if (mounted) {
|
|
|
setState(() {
|
|
|
_detections = detections;
|
|
|
- _isLocked = locked;
|
|
|
+ _isLocked = _consecutiveDetections >= _requiredConsecutive;
|
|
|
});
|
|
|
}
|
|
|
} catch (e) {
|