feat: implement base architecture and core repositories for weapon tracking and target analysis functionality

This commit is contained in:
streaper2
2026-05-08 20:29:18 +02:00
parent 5dd58da51c
commit 774dbfcf40
37 changed files with 3687 additions and 2713 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'dart:math' as math;
import 'package:image/image.dart' as img;
@@ -189,7 +190,7 @@ class ImageProcessingService {
);
}).toList();
} catch (e) {
print('Error detecting impacts: $e');
debugPrint('Error detecting impacts: $e');
return [];
}
}
@@ -236,14 +237,14 @@ class ImageProcessingService {
final fillRatios = <double>[];
final thresholds = <double>[];
print('Analyzing ${references.length} reference impacts...');
debugPrint('Analyzing ${references.length} reference impacts...');
for (int refIndex = 0; refIndex < references.length; refIndex++) {
final ref = references[refIndex];
final centerX = (ref.x * width).round().clamp(0, width - 1);
final centerY = (ref.y * height).round().clamp(0, height - 1);
print('Reference $refIndex at ($centerX, $centerY)');
debugPrint('Reference $refIndex at ($centerX, $centerY)');
// AMÉLIORATION : Recherche du point le plus sombre dans une zone plus large
int darkestX = centerX;
@@ -275,7 +276,7 @@ class ImageProcessingService {
if (darkestLum < 50 && r > 5) break;
}
print(' Darkest point at ($darkestX, $darkestY), lum=$darkestLum');
debugPrint(' Darkest point at ($darkestX, $darkestY), lum=$darkestLum');
// Now find the blob at the darkest point using adaptive threshold
final blobResult = _findBlobAtPoint(blurred, darkestX, darkestY, width, height);
@@ -286,15 +287,15 @@ class ImageProcessingService {
circularities.add(blobResult.circularity);
fillRatios.add(blobResult.fillRatio);
thresholds.add(blobResult.threshold);
print(' Found blob: size=${blobResult.size}, circ=${blobResult.circularity.toStringAsFixed(2)}, '
debugPrint(' Found blob: size=${blobResult.size}, circ=${blobResult.circularity.toStringAsFixed(2)}, '
'fill=${blobResult.fillRatio.toStringAsFixed(2)}, threshold=${blobResult.threshold.toStringAsFixed(0)}');
} else {
print(' No valid blob found at this reference');
debugPrint(' No valid blob found at this reference');
}
}
if (luminances.isEmpty) {
print('ERROR: No valid blobs found from any reference!');
debugPrint('ERROR: No valid blobs found from any reference!');
return null;
}
@@ -329,11 +330,11 @@ class ImageProcessingService {
avgDarkThreshold: avgThreshold,
);
print('Learned characteristics: $result');
debugPrint('Learned characteristics: $result');
return result;
} catch (e) {
print('Error analyzing reference impacts: $e');
debugPrint('Error analyzing reference impacts: $e');
return null;
}
}
@@ -680,7 +681,7 @@ class ImageProcessingService {
// Calculate minimum fill ratio - impacts pleins
final minFillRatio = (characteristics.avgFillRatio - 0.2).clamp(0.35, 0.85);
print('Detection params: thresholds=$thresholds, size=$minSize-$maxSize, '
debugPrint('Detection params: thresholds=$thresholds, size=$minSize-$maxSize, '
'circ>=$effectiveMinCircularity, fill>=$minFillRatio');
// Détecter avec plusieurs seuils et combiner les résultats
@@ -722,7 +723,7 @@ class ImageProcessingService {
return true;
}).toList();
print('Found ${filteredBlobs.length} impacts after filtering (from ${mergedBlobs.length} merged)');
debugPrint('Found ${filteredBlobs.length} impacts after filtering (from ${mergedBlobs.length} merged)');
// Convert to relative coordinates
return filteredBlobs.map((blob) {
@@ -733,7 +734,7 @@ class ImageProcessingService {
);
}).toList();
} catch (e) {
print('Error detecting impacts from references: $e');
debugPrint('Error detecting impacts from references: $e');
return [];
}
}
@@ -776,50 +777,6 @@ class ImageProcessingService {
return merged;
}
/// Detect dark spots with adaptive luminance range
List<_Blob> _detectDarkSpotsAdaptive(
img.Image image,
int minLuminance,
int maxLuminance,
int minSize,
int maxSize, {
double minCircularity = 0.5,
double minFillRatio = 0.5,
}) {
final width = image.width;
final height = image.height;
// Create binary mask of pixels within luminance range
final mask = List.generate(height, (_) => List.filled(width, false));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
final pixel = image.getPixel(x, y);
final luminance = img.getLuminance(pixel);
mask[y][x] = luminance >= minLuminance && luminance <= maxLuminance;
}
}
// Find connected components
final visited = List.generate(height, (_) => List.filled(width, false));
final blobs = <_Blob>[];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (mask[y][x] && !visited[y][x]) {
final blob = _floodFill(mask, visited, x, y, width, height);
if (blob.size >= minSize &&
blob.size <= maxSize &&
blob.circularity >= minCircularity &&
blob.fillRatio >= minFillRatio) {
blobs.add(blob);
}
}
}
}
return _filterOverlappingBlobs(blobs);
}
/// Detect dark spots in a grayscale image using blob detection
List<_Blob> _detectDarkSpots(