add ArUco but no activated

This commit is contained in:
gcw_4spBpAfv
2026-03-24 10:18:48 +08:00
parent d1ae364dbd
commit 704b20cde1
9 changed files with 1394 additions and 6 deletions

View File

@@ -8,7 +8,7 @@ import _thread
import json
import os
import binascii
from maix import time, camera
from maix import time
import threading
import config
from logger_manager import logger_manager
@@ -861,7 +861,8 @@ class LaserManager:
center_temp = None
radius_temp = None
if config.LASER_REQUIRE_IN_ELLIPSE:
result_img_temp, center_temp, radius_temp, method_temp, best_radius1_temp, ellipse_params_temp = vision.detect_circle_v3(frame, None)
# 使用统一的检测接口支持ArUco和传统方法
result_img_temp, center_temp, radius_temp, method_temp, best_radius1_temp, ellipse_params_temp = vision.detect_target(frame, None)
# 只有检测到靶心时才继续处理激光点
if center_temp is None or radius_temp is None:
@@ -1114,7 +1115,7 @@ class LaserManager:
return self._laser_point is not None
def compute_laser_position(self, circle_center, laser_point, radius, method):
def compute_laser_position(self, circle_center, laser_point, radius, method, ellipse_params=None):
"""计算激光相对于靶心的偏移量(单位:厘米)
Args:
@@ -1122,6 +1123,7 @@ class LaserManager:
laser_point: 激光点坐标 (x, y)
radius: 靶心半径(像素)
method: 检测方法("模糊" 或其他)
ellipse_params: 椭圆参数,用于透视校正(可选)
Returns:
(dx, dy): 激光相对于靶心的偏移量(厘米),如果输入无效则返回 (None, None)
@@ -1131,6 +1133,14 @@ class LaserManager:
cx, cy = circle_center
lx, ly = laser_point
# 如果有椭圆参数,使用透视校正计算
if ellipse_params is not None and method != "aruco":
return self._compute_with_perspective_correction(
circle_center, laser_point, radius, ellipse_params
)
# 传统计算方法
# r = 22.16 * 5
r = radius * 5
self.logger.debug(f"compute_laser_position: circle_center: {circle_center} laser_point: {laser_point} radius: {radius} method: {method} r: {r}")
@@ -1138,6 +1148,87 @@ class LaserManager:
target_y = (ly-cy)/r*100
self.logger.info(f"lx{lx} ly: {ly} cx: {cx} cy: {cy} result_x: {target_x} result_y: {-target_y} real_r_x: {lx-cx} real_r_y: {-1*(ly-cy)}")
return (target_x, -target_y)
def _compute_with_perspective_correction(self, circle_center, laser_point, radius, ellipse_params):
"""
使用透视校正计算激光偏移
当相机不正对靶子时,圆会变成椭圆。使用椭圆参数进行透视校正,
将图像坐标转换到物理坐标系,再计算偏移。
Args:
circle_center: 靶心中心坐标 (x, y)
laser_point: 激光点坐标 (x, y)
radius: 靶心半径(像素)
ellipse_params: ((center_x, center_y), (width, height), angle)
Returns:
(dx, dy): 校正后的偏移量(厘米)
"""
import math
try:
(ex, ey), (width, height), angle = ellipse_params
cx, cy = circle_center
lx, ly = laser_point
# 步骤1: 平移到椭圆中心
dx1 = lx - cx
dy1 = ly - cy
# 步骤2: 旋转坐标系,使椭圆轴与坐标轴对齐
angle_rad = math.radians(-angle)
cos_a = math.cos(angle_rad)
sin_a = math.sin(angle_rad)
x_rot = dx1 * cos_a - dy1 * sin_a
y_rot = dx1 * sin_a + dy1 * cos_a
# 步骤3: 归一化到单位圆
# 椭圆半轴
a = width / 2.0
b = height / 2.0
# 归一化坐标
if a > 0 and b > 0:
x_norm = x_rot / a
y_norm = y_rot / b
else:
x_norm = x_rot
y_norm = y_rot
# 步骤4: 计算物理距离
# 使用平均半径作为参考
avg_radius = (a + b) / 2.0
pixels_per_cm = avg_radius / 20.0 # 假设靶心半径20cm对应avg_radius像素
if pixels_per_cm > 0:
# 归一化距离(单位:靶心半径的倍数)
norm_distance = math.sqrt(x_norm**2 + y_norm**2)
# 转换为厘米假设靶心半径20cm
distance_cm = norm_distance * 20.0
# 计算方向
angle_offset = math.atan2(y_norm, x_norm)
dx_cm = distance_cm * math.cos(angle_offset)
dy_cm = -distance_cm * math.sin(angle_offset) # Y轴翻转
self.logger.debug(f"[PERSPECTIVE] 原始偏移: ({dx1:.1f}, {dy1:.1f})px, "
f"校正后: ({dx_cm:.2f}, {dy_cm:.2f})cm, "
f"椭圆: ({width:.1f}, {height:.1f}), 角度: {angle:.1f}°")
return (dx_cm, dy_cm)
else:
# 回退到直接计算
r = radius * 5
return ((lx-cx)/r*100, -(ly-cy)/r*100)
except Exception as e:
self.logger.error(f"[PERSPECTIVE] 透视校正计算失败: {e}")
# 回退到直接计算
r = radius * 5
return ((lx-cx)/r*100, -(ly-cy)/r*100)
# # 根据检测方法动态调整靶心物理半径(简化模型)
# circle_r = (radius / 4.0) * 20.0 if method == "模糊" else (68 / 16.0) * 20.0