Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bde549d91 | ||
|
|
d96ca4d031 | ||
|
|
ced66682ed | ||
|
|
a09b45738a | ||
|
|
e4d8454947 | ||
|
|
c09189332d | ||
|
|
a00baa1770 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
id: t11
|
||||
name: t11
|
||||
version: 2.18.2
|
||||
version: 3.0.5
|
||||
author: t11
|
||||
icon: ''
|
||||
desc: t11
|
||||
@@ -18,8 +18,8 @@ files:
|
||||
- laser_manager.py
|
||||
- logger_manager.py
|
||||
- main.py
|
||||
- model_317828.cvimodel
|
||||
- model_317828.mud
|
||||
- model_285484.cvimodel
|
||||
- model_285484.mud
|
||||
- network.py
|
||||
- ota_curl.sh
|
||||
- ota_manager.py
|
||||
|
||||
+6
-15
@@ -66,6 +66,12 @@ class CameraManager:
|
||||
with self._camera_lock:
|
||||
if self._camera is None:
|
||||
self._camera = camera.Camera(width, height)
|
||||
v_flip = getattr(config, 'CAMERA_V_FLIP', False)
|
||||
h_mirror = getattr(config, 'CAMERA_H_MIRROR', False)
|
||||
if v_flip:
|
||||
self._camera.vflip(1)
|
||||
if h_mirror:
|
||||
self._camera.hmirror(1)
|
||||
|
||||
return self._camera
|
||||
|
||||
@@ -111,21 +117,6 @@ class CameraManager:
|
||||
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
|
||||
|
||||
def show(self, image):
|
||||
|
||||
@@ -241,10 +241,10 @@ TRIANGLE_BLACKHAT_KERNEL_FRAC = 0.018 # 核大小 ≈ min(h,w)*frac,取奇数
|
||||
# ── YOLO(NPU) 靶环 ROI → 裁剪后再跑三角形(减小 CPU 处理面积)──────────────────
|
||||
# 日志里 net_in=W×H 来自 .mud 模型(det.input_width/height),不是这里配置的。
|
||||
TRIANGLE_YOLO_ROI_ENABLE = True
|
||||
TRIANGLE_YOLO_MODEL_PATH = APP_DIR + "/model_317828.mud"
|
||||
TRIANGLE_YOLO_MODEL_PATH = APP_DIR + "/model_270139.mud"
|
||||
# 参与 ROI 的类别:多类时只填「整靶/靶环」的 id;不要填角标类,否则 union 仍可对,但 largest 会偏小。
|
||||
TRIANGLE_YOLO_RING_CLASS_IDS = (0,)
|
||||
TRIANGLE_YOLO_CONF_TH = 0.9
|
||||
TRIANGLE_YOLO_CONF_TH = 0.7
|
||||
TRIANGLE_YOLO_IOU_TH = 0.45
|
||||
# YOLO 首次/临界帧可能在高阈值下 0 框;启用后仅在 0 候选时用较低阈值重试一次。
|
||||
# 后续仍会经过 min_box_side、ROI aspect、三角形几何校验,避免直接放大假阳性。
|
||||
@@ -271,9 +271,9 @@ TRIANGLE_YOLO_PRELOAD_ON_BOOT = False
|
||||
|
||||
# YOLO target size classification: class 0=20cm, class 1=40cm.
|
||||
TARGET_CLASS_YOLO_ENABLE = True
|
||||
TARGET_CLASS_YOLO_MODEL_PATH = APP_DIR + "/model_317828.mud"
|
||||
TARGET_CLASS_YOLO_MODEL_PATH = APP_DIR + "/model_285484.mud"
|
||||
TARGET_CLASS_YOLO_LABELS = (20, 40)
|
||||
TARGET_CLASS_YOLO_CONF_TH = 0.66
|
||||
TARGET_CLASS_YOLO_CONF_TH = 0.50
|
||||
TARGET_CLASS_YOLO_IOU_TH = 0.45
|
||||
TARGET_CLASS_YOLO_RETRY_ON_EMPTY = False
|
||||
TARGET_CLASS_YOLO_RETRY_CONF_TH = 0.25
|
||||
@@ -333,17 +333,14 @@ LOG_QUEUE_MAXSIZE = 10000 # 日志队列上限
|
||||
MAX_CMD_THREADS = 10 # 并发命令线程上限(防止服务器下发命令时无限创建线程)
|
||||
|
||||
# ==================== 图像保存配置 ====================
|
||||
SAVE_IMAGE_ENABLED = True # 是否保存图像(True=保存,False=不保存)
|
||||
SAVE_IMAGE_ON_FAILURE = False # 检测失败时是否强制保存图像(供调试测试用)
|
||||
SAVE_IMAGE_ENABLED = False # 是否保存图像(True=保存,False=不保存)
|
||||
SAVE_IMAGE_ON_FAILURE = True # 检测失败时是否强制保存图像(供调试测试用)
|
||||
PHOTO_DIR = "/root/phot" # 照片存储目录
|
||||
MAX_IMAGES = 1000
|
||||
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 = False # 关闭拍摄实时显示
|
||||
SHOW_CAMERA_PHOTO_WHILE_SHOOTING = False # 是否在拍摄时显示摄像头图像(True=显示,False=不显示),建议在连着USB测试过程中打开
|
||||
|
||||
# ==================== OTA配置 ====================
|
||||
MAX_BACKUPS = 5
|
||||
|
||||
@@ -172,10 +172,8 @@ def cmd_str():
|
||||
and bool(getattr(config, "TARGET_CLASS_YOLO_PRELOAD_ON_BOOT", True))
|
||||
)
|
||||
_preload_yolo = _preload_yolo or _need_black_preload or _need_target_preload
|
||||
if _preload_yolo and not os.path.exists(f"{config.APP_DIR}/ota_pending.json"):
|
||||
if _preload_yolo:
|
||||
preload_yolo_detector(logger)
|
||||
elif _preload_yolo and logger:
|
||||
logger.warning("[YOLO] ota_pending.json found; skip model preload until rollback check")
|
||||
except Exception as e:
|
||||
if logger:
|
||||
logger.warning(f"[YOLO-ROI] 启动预加载异常(不影响后续射箭): {e}")
|
||||
@@ -257,11 +255,7 @@ def cmd_str():
|
||||
network_manager.read_device_id()
|
||||
|
||||
# 5. 创建照片存储目录(如果启用图像保存或检测失败时强制保存)
|
||||
if (
|
||||
config.SAVE_IMAGE_ENABLED
|
||||
or getattr(config, "SAVE_IMAGE_ON_FAILURE", False)
|
||||
or getattr(config, "SAVE_RAW_IMAGE_ENABLED", False)
|
||||
):
|
||||
if config.SAVE_IMAGE_ENABLED or getattr(config, "SAVE_IMAGE_ON_FAILURE", False):
|
||||
photo_dir = config.PHOTO_DIR
|
||||
if photo_dir not in os.listdir("/root"):
|
||||
try:
|
||||
@@ -393,7 +387,7 @@ def cmd_str():
|
||||
# 触发后需等气压降到触发值以下才重新检测增量
|
||||
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) > 250 and enable_check:
|
||||
hardware_manager.start_idle_timer() # 重新计时
|
||||
last_adc_trigger = current_time
|
||||
trigger_adc_val = adc_val # 记录触发时的气压值
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
|
||||
[basic]
|
||||
type = cvimodel
|
||||
model = model_317828.cvimodel
|
||||
model = model_285484.cvimodel
|
||||
|
||||
[extra]
|
||||
model_type = yolov5
|
||||
+5
-13
@@ -8,7 +8,7 @@ from laser_manager import laser_manager
|
||||
from logger_manager import logger_manager
|
||||
from network import network_manager
|
||||
from triangle_target import load_camera_from_xml, load_triangle_positions, try_triangle_scoring
|
||||
from vision import estimate_distance, detect_circle_v3, enqueue_save_shot, enqueue_save_raw_shot
|
||||
from vision import estimate_distance, detect_circle_v3, enqueue_save_shot
|
||||
from maix import image, time
|
||||
|
||||
# 缓存相机标定与三角形位置,避免每次射箭重复读磁盘
|
||||
@@ -322,11 +322,6 @@ def process_shot(adc_val):
|
||||
try:
|
||||
frame = camera_manager.read_frame()
|
||||
|
||||
# 在任何检测和绘图之前复制原始帧;默认由配置关闭,不增加量产开销。
|
||||
from shot_id_generator import shot_id_generator
|
||||
shot_id = shot_id_generator.generate_id()
|
||||
enqueue_save_raw_shot(frame, shot_id)
|
||||
|
||||
# 网络事件移到拍照之后,避免阻塞拍照
|
||||
network_manager.safe_enqueue({"shoot_event": "start"}, msg_type=2, high=True)
|
||||
|
||||
@@ -385,6 +380,10 @@ def process_shot(adc_val):
|
||||
if dx is None and dy is None and logger:
|
||||
logger.warning("[MAIN] 未检测到偏移量(三角形与圆形均失败),但会保存图像")
|
||||
|
||||
# 生成射箭ID
|
||||
from shot_id_generator import shot_id_generator
|
||||
shot_id = shot_id_generator.generate_id()
|
||||
|
||||
if logger:
|
||||
logger.info(f"[MAIN] 射箭ID: {shot_id}")
|
||||
|
||||
@@ -442,13 +441,6 @@ def process_shot(adc_val):
|
||||
inner_data["ellipse_center_x"] = None
|
||||
inner_data["ellipse_center_y"] = None
|
||||
|
||||
upload_time_ms = int(time_std.time() * 1000)
|
||||
upload_time_sec, upload_time_millis = divmod(upload_time_ms, 1000)
|
||||
inner_data["upload_time"] = (
|
||||
time_std.strftime("%Y-%m-%d %H:%M:%S", time_std.localtime(upload_time_sec))
|
||||
+ f".{upload_time_millis:03d}"
|
||||
)
|
||||
|
||||
report_data = {"cmd": 1, "data": inner_data}
|
||||
if logger:
|
||||
logger.info(
|
||||
|
||||
Binary file not shown.
+1
-5
@@ -30,8 +30,4 @@
|
||||
# 2.15.17 修复wifi连接问题
|
||||
# 2.15.18 wifi连接成功重新登录
|
||||
# 2.16.4 优化射箭延迟
|
||||
# 2.17.0 yolo标靶类别识别
|
||||
# 2.17.1 26-08-19 17:39 压力传感修改 增量方式
|
||||
# 2.17.2 26-08-24 17:56 靶纸识别模型更替
|
||||
# 2.17.3 26-08-25 9:57 原图拍摄开关
|
||||
# 2.17.4 26-08-25 14:57 模型修改
|
||||
# 2.17.0 yolo标靶类别识别
|
||||
+1
-1
@@ -4,6 +4,6 @@
|
||||
应用版本号
|
||||
每次 OTA 更新时,只需要更新这个文件中的版本号
|
||||
"""
|
||||
VERSION = '2.18.2'
|
||||
VERSION = '3.0.5'
|
||||
|
||||
|
||||
|
||||
@@ -902,16 +902,13 @@ def _save_shot_image_impl(img_cv, center, radius, method, ellipse_params,
|
||||
|
||||
|
||||
def _save_worker_loop():
|
||||
"""存图 worker:处理标注图和可选的纯原图任务。"""
|
||||
"""存图 worker:从队列取任务并调用 _save_shot_image_impl。"""
|
||||
while True:
|
||||
try:
|
||||
item = _save_queue.get()
|
||||
if item is None:
|
||||
break
|
||||
if isinstance(item, dict) and item.get("kind") == "raw":
|
||||
_save_raw_image_impl(item["img_cv"], item["shot_id"], item["photo_dir"])
|
||||
else:
|
||||
_save_shot_image_impl(*item)
|
||||
_save_shot_image_impl(*item)
|
||||
except Exception as e:
|
||||
logger = logger_manager.logger
|
||||
if logger:
|
||||
@@ -939,52 +936,6 @@ def start_save_shot_worker():
|
||||
logger.info("[VISION] 存图 worker 线程已启动")
|
||||
|
||||
|
||||
def _save_raw_image_impl(img_cv, shot_id, photo_dir):
|
||||
"""保存未标注、未裁剪的完整原始帧。"""
|
||||
logger = logger_manager.logger
|
||||
try:
|
||||
os.makedirs(photo_dir, exist_ok=True)
|
||||
filename = os.path.join(photo_dir, f"shot_{shot_id}_raw.jpg")
|
||||
image.cv2image(img_cv, False, False).save(filename)
|
||||
prune_old_images_in_dir(
|
||||
photo_dir,
|
||||
getattr(config, "RAW_IMAGE_MAX_IMAGES", config.MAX_IMAGES),
|
||||
logger,
|
||||
"[VISION-RAW]",
|
||||
)
|
||||
if logger:
|
||||
logger.info(f"[VISION-RAW] 已保存纯原图: {filename}")
|
||||
return filename
|
||||
except Exception as e:
|
||||
if logger:
|
||||
logger.error(f"[VISION-RAW] 保存纯原图失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def enqueue_save_raw_shot(frame, shot_id, photo_dir=None):
|
||||
"""复制并异步保存原始帧;由 SAVE_RAW_IMAGE_ENABLED 控制是否启用。"""
|
||||
if not getattr(config, "SAVE_RAW_IMAGE_ENABLED", False):
|
||||
return
|
||||
if photo_dir is None:
|
||||
photo_dir = getattr(config, "RAW_IMAGE_DIR", os.path.join(config.PHOTO_DIR, "raw"))
|
||||
try:
|
||||
img_copy = np.copy(image.image2cv(frame, False, False))
|
||||
_save_queue.put_nowait({
|
||||
"kind": "raw",
|
||||
"img_cv": img_copy,
|
||||
"shot_id": shot_id,
|
||||
"photo_dir": photo_dir,
|
||||
})
|
||||
except queue.Full:
|
||||
logger = logger_manager.logger
|
||||
if logger:
|
||||
logger.warning("[VISION-RAW] 存图队列已满,跳过本次纯原图保存")
|
||||
except Exception as e:
|
||||
logger = logger_manager.logger
|
||||
if logger:
|
||||
logger.error(f"[VISION-RAW] 复制纯原图失败: {e}")
|
||||
|
||||
|
||||
def enqueue_save_shot(result_img, center, radius, method, ellipse_params,
|
||||
laser_point, distance_m, shot_id=None, photo_dir=None,
|
||||
yolo_roi_xyxy=None, force_save=False):
|
||||
|
||||
Reference in New Issue
Block a user