From 631f2a1f4a3fc2b923823c548776f15518bc9d27 Mon Sep 17 00:00:00 2001 From: sladro Date: Fri, 27 Feb 2026 22:03:28 +0800 Subject: [PATCH] =?UTF-8?q?o4.6=E5=81=9A=E4=BA=86=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configs/test_cam1_ppe11_yolo_debug.json | 2 +- plugins/ai_yolo/ai_yolo_node.cpp | 24 +++++++++++++---------- plugins/osd/osd_node.cpp | 26 +++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/configs/test_cam1_ppe11_yolo_debug.json b/configs/test_cam1_ppe11_yolo_debug.json index 8de7b63..365cba2 100644 --- a/configs/test_cam1_ppe11_yolo_debug.json +++ b/configs/test_cam1_ppe11_yolo_debug.json @@ -35,7 +35,7 @@ "dst_h": 768, "dst_format": "rgb", "dst_packed": true, - "resize_mode": "letterbox", + "resize_mode": "stretch", "keep_ratio": false, "rga_gate": "cam_ppe11_yolo_debug", "use_rga": true diff --git a/plugins/ai_yolo/ai_yolo_node.cpp b/plugins/ai_yolo/ai_yolo_node.cpp index f76db2e..3a7fc26 100644 --- a/plugins/ai_yolo/ai_yolo_node.cpp +++ b/plugins/ai_yolo/ai_yolo_node.cpp @@ -951,11 +951,11 @@ private: NMS(valid_count, boxes, class_ids, indices, c, nms_thresh_); } - const DetCoordContext coord_ctx = BuildDetCoordContext(*frame, model_input_w_, model_input_h_); - auto det_result = std::make_shared(); - det_result->img_w = coord_ctx.out_w; - det_result->img_h = coord_ctx.out_h; + // README 约定: img_w/img_h = 推理输入宽/高(当前帧空间) + // 坐标缩放由下游 preprocess 的 ScaleMeta 负责 + det_result->img_w = frame->width; + det_result->img_h = frame->height; det_result->model_name = (yolo_version_ == YoloVersion::V5) ? "yolov5" : "yolov8"; for (int i = 0; i < valid_count && det_result->items.size() < kMaxDetections; ++i) { @@ -975,7 +975,10 @@ private: Detection det; det.cls_id = cls_id; det.score = obj_probs[i]; - det.bbox = DecodeToOutputRect(x1, y1, w, h, coord_ctx); + det.bbox.x = std::max(0.0f, std::min(x1, static_cast(frame->width))); + det.bbox.y = std::max(0.0f, std::min(y1, static_cast(frame->height))); + det.bbox.w = std::max(0.0f, std::min(w, static_cast(frame->width) - det.bbox.x)); + det.bbox.h = std::max(0.0f, std::min(h, static_cast(frame->height) - det.bbox.y)); det.track_id = -1; if (debug_det_ && det_result->items.size() < 5 && processed_ < 20) { @@ -1101,11 +1104,9 @@ private: NMS(valid_count, boxes, class_ids, indices, c, nms_thresh_); } - const DetCoordContext coord_ctx = BuildDetCoordContext(*frame, model_input_w_, model_input_h_); - auto det_result = std::make_shared(); - det_result->img_w = coord_ctx.out_w; - det_result->img_h = coord_ctx.out_h; + det_result->img_w = frame->width; + det_result->img_h = frame->height; det_result->model_name = (yolo_version_ == YoloVersion::V5) ? "yolov5" : "yolov8"; for (int i = 0; i < valid_count && det_result->items.size() < kMaxDetections; ++i) { @@ -1125,7 +1126,10 @@ private: Detection det; det.cls_id = cls_id; det.score = obj_probs[i]; - det.bbox = DecodeToOutputRect(x1, y1, w, h, coord_ctx); + det.bbox.x = std::max(0.0f, std::min(x1, static_cast(frame->width))); + det.bbox.y = std::max(0.0f, std::min(y1, static_cast(frame->height))); + det.bbox.w = std::max(0.0f, std::min(w, static_cast(frame->width) - det.bbox.x)); + det.bbox.h = std::max(0.0f, std::min(h, static_cast(frame->height) - det.bbox.y)); det.track_id = -1; if (debug_det_ && det_result->items.size() < 5 && processed_ < 20) { diff --git a/plugins/osd/osd_node.cpp b/plugins/osd/osd_node.cpp index d3dfed1..9cfd4c0 100644 --- a/plugins/osd/osd_node.cpp +++ b/plugins/osd/osd_node.cpp @@ -77,6 +77,21 @@ Rect MapRectToFrame(const Rect& in, int src_w, int src_h, int dst_w, int dst_h) return out; } +// 利用 transform_meta 将原图空间坐标正确映射回当前帧空间 +// 正向变换: frame_x = orig_x * scale_x + pad_x +Rect MapRectWithTransform(const Rect& in, const FrameTransformMeta& tx, int frame_w, int frame_h) { + const float fw = static_cast(frame_w); + const float fh = static_cast(frame_h); + Rect out{}; + out.x = std::max(0.0f, in.x * tx.scale_x + tx.pad_x); + out.y = std::max(0.0f, in.y * tx.scale_y + tx.pad_y); + out.w = std::max(0.0f, in.w * tx.scale_x); + out.h = std::max(0.0f, in.h * tx.scale_y); + if (out.x + out.w > fw) out.w = std::max(0.0f, fw - out.x); + if (out.y + out.h > fh) out.h = std::max(0.0f, fh - out.y); + return out; +} + #if defined(RK3588_ENABLE_RGA) inline uint32_t PackColorArgb(const Color& c) { return (0xFFu << 24) | (static_cast(c.r) << 16) | @@ -578,6 +593,11 @@ private: const int det_w = frame->det->img_w > 0 ? frame->det->img_w : w; const int det_h = frame->det->img_h > 0 ? frame->det->img_h : h; const bool map_det_to_frame = (det_w != w || det_h != h); + // 优先使用 transform_meta 做 letterbox 感知的坐标映射 + const bool use_transform = map_det_to_frame && frame->transform_meta && + frame->transform_meta->valid && + frame->transform_meta->scale_x > 1e-6f && + frame->transform_meta->scale_y > 1e-6f; uint8_t* data = frame->planes[0].data ? frame->planes[0].data : frame->data; PixelFormat fmt = frame->format; @@ -604,7 +624,8 @@ private: } else { bool ok = true; for (const auto& det : frame->det->items) { - const Rect draw = map_det_to_frame ? MapRectToFrame(det.bbox, det_w, det_h, w, h) : det.bbox; + const Rect draw = use_transform ? MapRectWithTransform(det.bbox, *frame->transform_meta, w, h) + : (map_det_to_frame ? MapRectToFrame(det.bbox, det_w, det_h, w, h) : det.bbox); int x = Clamp(static_cast(draw.x), 0, w - 1); int y = Clamp(static_cast(draw.y), 0, h - 1); int rw = static_cast(draw.w); @@ -654,7 +675,8 @@ private: } for (const auto& det : frame->det->items) { - const Rect draw = map_det_to_frame ? MapRectToFrame(det.bbox, det_w, det_h, w, h) : det.bbox; + const Rect draw = use_transform ? MapRectWithTransform(det.bbox, *frame->transform_meta, w, h) + : (map_det_to_frame ? MapRectToFrame(det.bbox, det_w, det_h, w, h) : det.bbox); int x1 = static_cast(draw.x); int y1 = static_cast(draw.y); int x2 = static_cast(draw.x + draw.w);