correction du centrage des vecteurs de zone (cercle) pour le plotting

This commit is contained in:
2026-02-21 10:22:18 +01:00
parent 2e81f4b69e
commit d4cb179fde
4 changed files with 298 additions and 58 deletions

View File

@@ -45,14 +45,14 @@ class OpenCVTargetService {
final circles = cv.HoughCircles(
blurred,
cv.HOUGH_GRADIENT,
1, // dp: Inverse ratio of the accumulator resolution to the image resolution
(img.rows / 8)
.toDouble(), // minDist: Minimum distance between the centers of the detected circles
param1: 100, // param1: Gradient value for Canny edge detection
1, // dp
(img.rows / 16)
.toDouble(), // minDist decreased to allow more rings in same general area
param1: 100, // Canny edge detection
param2:
30, // param2: Accumulator threshold for the circle centers at the detection stage
minRadius: img.cols ~/ 20, // minRadius
maxRadius: img.cols ~/ 2, // maxRadius
60, // Accumulator threshold (higher = fewer false circles, more accurate)
minRadius: img.cols ~/ 20,
maxRadius: img.cols ~/ 2,
);
// HoughCircles returns a Mat of shape (1, N, 3) where N is number of circles.
@@ -79,8 +79,8 @@ class OpenCVTargetService {
cv.HOUGH_GRADIENT,
1,
(img.rows / 8).toDouble(),
param1: 50,
param2: 20,
param1: 100,
param2: 40,
minRadius: img.cols ~/ 20,
maxRadius: img.cols ~/ 2,
);
@@ -137,18 +137,22 @@ class OpenCVTargetService {
for (final circle in detected) {
bool added = false;
for (final cluster in clusters) {
// Check distance to cluster center (average of existing)
double clusterX = 0;
double clusterY = 0;
// Calculate the actual center of the cluster based on the smallest circle (the likely bullseye)
double clusterCenterX = cluster.first.x;
double clusterCenterY = cluster.first.y;
double minRadiusInCluster = cluster.first.r;
for (final c in cluster) {
clusterX += c.x;
clusterY += c.y;
if (c.r < minRadiusInCluster) {
minRadiusInCluster = c.r;
clusterCenterX = c.x;
clusterCenterY = c.y;
}
}
clusterX /= cluster.length;
clusterY /= cluster.length;
final dist = math.sqrt(
math.pow(circle.x - clusterX, 2) + math.pow(circle.y - clusterY, 2),
math.pow(circle.x - clusterCenterX, 2) +
math.pow(circle.y - clusterCenterY, 2),
);
if (dist < tolerance) {
@@ -171,10 +175,10 @@ class OpenCVTargetService {
for (final cluster in clusters) {
// Score calculation
// Base score = number of circles * 10
double score = cluster.length * 10.0;
// Base score = number of circles squared (heavily favor concentric rings)
double score = math.pow(cluster.length, 2).toDouble() * 10.0;
// Penalize distance from center
// Small penalty for distance from center (only as tie-breaker)
double cx = 0, cy = 0;
for (final c in cluster) {
cx += c.x;
@@ -188,7 +192,8 @@ class OpenCVTargetService {
);
final relDist = distFromCenter / math.min(width, height);
score -= relDist * 5.0; // Moderate penalty for off-center
score -=
relDist * 2.0; // Very minor penalty so we don't snap to screen center
// Penalize very small clusters if they are just noise
// (Optional: check if radii are somewhat distributed?)