diff --git a/app.yaml b/app.yaml index 8daa9fa..c841089 100644 --- a/app.yaml +++ b/app.yaml @@ -1,6 +1,6 @@ id: t11 name: t11 -version: 2.17.15 +version: 2.17.18 author: t11 icon: '' desc: t11 diff --git a/camera_manager.py b/camera_manager.py index 67b61dc..0f28ed4 100644 --- a/camera_manager.py +++ b/camera_manager.py @@ -8,15 +8,6 @@ import threading import config from logger_manager import logger_manager -_USE_CV = False -try: - import cv2 - import numpy as np - from maix import image as _maix_image - _USE_CV = True -except ImportError: - pass - class CameraManager: """相机管理器(单例)""" @@ -110,23 +101,7 @@ class CameraManager: with self._camera_lock: if self._camera is None: self.init_camera() - frame = self._camera.read() - if frame is not None and _USE_CV: - try: - v_flip = getattr(config, 'CAMERA_V_FLIP', False) - h_mirror = getattr(config, 'CAMERA_H_MIRROR', False) - if v_flip or h_mirror: - img_cv = _maix_image.image2cv(frame, False, False) - if v_flip and h_mirror: - img_cv = cv2.flip(img_cv, -1) - elif v_flip: - img_cv = cv2.flip(img_cv, 0) - elif h_mirror: - img_cv = cv2.flip(img_cv, 1) - frame = _maix_image.cv2image(img_cv, False, False) - except Exception: - pass - return frame + return self._camera.read() def show(self, image): """ diff --git a/config.py b/config.py index 38751a5..5819b90 100644 --- a/config.py +++ b/config.py @@ -15,8 +15,6 @@ LOCAL_FILENAME = APP_DIR + "/main_tmp.py" # 相机初始化分辨率(CameraManager / main.py 使用) CAMERA_WIDTH = 640 CAMERA_HEIGHT = 480 -CAMERA_V_FLIP = True # 摄像头垂直翻转(上下颠倒时设为 True) -CAMERA_H_MIRROR = True # 摄像头水平镜像(左右反了时设为 True) # 三角形检测缩图比例:默认按相机最长边缩到 1/2(性能更稳;可按需调整) # 取值范围建议 (0.25 ~ 1.0];1.0 表示不缩图 @@ -329,16 +327,16 @@ MAX_CMD_THREADS = 10 # 并发命令线程上限(防止服务器下 # ==================== 图像保存配置 ==================== SAVE_IMAGE_ENABLED = True # 是否保存图像(True=保存,False=不保存) -SAVE_IMAGE_ON_FAILURE = False # 检测失败时是否强制保存图像(供调试测试用) +SAVE_IMAGE_ON_FAILURE = True # 检测失败时是否强制保存图像(供调试测试用) PHOTO_DIR = "/root/phot" # 照片存储目录 MAX_IMAGES = 1000 -SAVE_RAW_IMAGE_ENABLED = True # 额外保存完整原始帧(不画框、不画点、不裁剪) +SAVE_RAW_IMAGE_ENABLED = False # 额外保存完整原始帧(不画框、不画点、不裁剪) RAW_IMAGE_DIR = PHOTO_DIR + "/raw" RAW_IMAGE_MAX_IMAGES = MAX_IMAGES # Stage2 调试目录(默认 PHOTO_DIR/stage2_roi)内 JPEG 最多保留张数;None 表示与 MAX_IMAGES 相同 TRIANGLE_BLACK_YOLO_STAGE2_ROI_MAX_IMAGES = None -SHOW_CAMERA_PHOTO_WHILE_SHOOTING = True # 是否在拍摄时显示摄像头图像(True=显示,False=不显示),建议在连着USB测试过程中打开 +SHOW_CAMERA_PHOTO_WHILE_SHOOTING = False # 是否在拍摄时显示摄像头图像(True=显示,False=不显示),建议在连着USB测试过程中打开 # ==================== OTA配置 ==================== MAX_BACKUPS = 5 diff --git a/main.py b/main.py index 5b62775..22760a2 100644 --- a/main.py +++ b/main.py @@ -385,11 +385,11 @@ def cmd_str(): pressure_max = adc_val if len(pressure_buf) >= PRESSURE_BATCH_SIZE: _flush_pressure_buf("batch") - # 突变增量检测:压力增量大于300时触发 + # 突变增量检测:压力增量大于400时触发 # 触发后需等气压降到触发值以下才重新检测增量 if adc_val < trigger_adc_val : enable_check = True - if (adc_val - last_adc_val) > 500 and enable_check: + if (adc_val - last_adc_val) > 200 and enable_check: hardware_manager.start_idle_timer() # 重新计时 last_adc_trigger = current_time trigger_adc_val = adc_val # 记录触发时的气压值 diff --git a/shoot_manager.py b/shoot_manager.py index ca433e1..bf3988f 100644 --- a/shoot_manager.py +++ b/shoot_manager.py @@ -59,6 +59,7 @@ def analyze_shot(frame, laser_point=None): """ logger = logger_manager.logger from datetime import datetime + yellow_algorithm_ms = 0.0 # ── Step 1: 确定激光点 ──────────────────────────────────────────────────── laser_point_method = None @@ -74,7 +75,11 @@ def analyze_shot(frame, laser_point=None): logger.info(f"[算法] 使用校准值: {laser_manager.laser_point}") else: # 动态模式:先做一次无激光点检测以估算距离,再推算激光点 - _, _, _, _, best_radius1_temp, _ = detect_circle_v3(frame, None) + _t_yellow = time_std.perf_counter() + try: + _, _, _, _, best_radius1_temp, _ = detect_circle_v3(frame, None) + finally: + yellow_algorithm_ms += (time_std.perf_counter() - _t_yellow) * 1000.0 distance_m_first = estimate_distance(best_radius1_temp) if best_radius1_temp else None if distance_m_first and distance_m_first > 0: laser_point = laser_manager.calculate_laser_point_from_distance(distance_m_first) @@ -119,6 +124,7 @@ def analyze_shot(frame, laser_point=None): "laser_point": laser_point, "laser_point_method": laser_point_method, "offset_method": "yellow_ellipse" if ellipse_params else "yellow_circle", "distance_method": "yellow_radius", + "yellow_algorithm_ms": float(yellow_algorithm_ms), } if yolo_roi_xyxy is not None: out["yolo_roi_xyxy"] = yolo_roi_xyxy @@ -126,9 +132,12 @@ def analyze_shot(frame, laser_point=None): if not use_tri: # 三角形未配置,直接跑圆形检测 - return _build_circle_result( - detect_circle_v3(frame, laser_point, img_cv=img_cv) - ) + _t_yellow = time_std.perf_counter() + try: + cdata = detect_circle_v3(frame, laser_point, img_cv=img_cv) + finally: + yellow_algorithm_ms += (time_std.perf_counter() - _t_yellow) * 1000.0 + return _build_circle_result(cdata) # ── Step 4: 先独占跑三角形,超时或失败后再跑圆形(不与圆心并行,避免抢 CPU)── roi_xyxy = None @@ -281,6 +290,7 @@ def analyze_shot(frame, laser_point=None): "laser_point": laser_point, "laser_point_method": laser_point_method, "offset_method": tri.get("offset_method") or "triangle_homography", "distance_method": tri.get("distance_method") or "pnp_triangle", + "yellow_algorithm_ms": float(yellow_algorithm_ms), "tri_markers": tri.get("markers", []), "tri_markers_completed": tri.get("markers_completed", []), "tri_homography": tri.get("homography"), @@ -301,7 +311,11 @@ def analyze_shot(frame, laser_point=None): # 三角形超时或失败 → 跑圆心;圆心跑完后再检查三角形是否已结束 try: - cdata = detect_circle_v3(frame, laser_point, img_cv=img_cv) + _t_yellow = time_std.perf_counter() + try: + cdata = detect_circle_v3(frame, laser_point, img_cv=img_cv) + finally: + yellow_algorithm_ms += (time_std.perf_counter() - _t_yellow) * 1000.0 except Exception as e: logger.error(f"[CIRCLE] 圆形检测异常: {e}") cdata = (frame, None, None, None, None, None) @@ -337,10 +351,15 @@ def process_shot(adc_val): # Classify only the current shot frame; never reuse a previous result. target_class_result = None + yolo_target_ms = 0.0 try: from target_roi_yolo import try_get_target_class_from_yolo - target_class_result = try_get_target_class_from_yolo(frame, logger=logger) + _t_yolo_target = time_std.perf_counter() + try: + target_class_result = try_get_target_class_from_yolo(frame, logger=logger) + finally: + yolo_target_ms = (time_std.perf_counter() - _t_yolo_target) * 1000.0 if logger: logger.info(f"[YOLO-TARGET] 当前箭业务结果: {target_class_result}") except Exception as exc: @@ -370,6 +389,7 @@ def process_shot(adc_val): laser_point_method = analysis_result["laser_point_method"] offset_method = analysis_result.get("offset_method", "yellow_circle") distance_method = analysis_result.get("distance_method", "yellow_radius") + yellow_algorithm_ms = float(analysis_result.get("yellow_algorithm_ms", 0.0) or 0.0) tri_markers = analysis_result.get("tri_markers", []) tri_markers_completed = analysis_result.get("tri_markers_completed", []) tri_homography = analysis_result.get("tri_homography") @@ -419,7 +439,9 @@ def process_shot(adc_val): "r": 20.0, # 保留字段(服务端当前忽略,物理外环半径 cm) "target_class": target_label, "target_class_confidence": ( - float(target_confidence) if target_confidence is not None else None + round(float(target_confidence), 2) + if target_confidence is not None + else None ), "d": round((distance_m or 0.0) * 100), "d_laser": round((laser_distance_m or 0.0) * 100), @@ -431,6 +453,8 @@ def process_shot(adc_val): "target_y": float(y), "offset_method": offset_method, "distance_method": distance_method, + "yellow_algorithm_ms": round(yellow_algorithm_ms, 2), + "yolo_target_ms": round(float(yolo_target_ms), 2), } if ellipse_params: diff --git a/version.py b/version.py index 1622991..c6a8b6c 100644 --- a/version.py +++ b/version.py @@ -4,6 +4,6 @@ 应用版本号 每次 OTA 更新时,只需要更新这个文件中的版本号 """ -VERSION = '2.17.15' +VERSION = '2.17.18'