import numpy as np from hbm_runtime import HB_HBMRuntime import os import cv2 hb_dtype_map = { "U8": np.uint8, "S8": np.int8, "F32": np.float32, "F16": np.float16, "U16": np.uint16, "S16": np.int16, "S32": np.int32, "U32": np.uint32, "BOOL8": np.bool_, } MODEL_PATH = "../models/cowCheck/det/det_640x640.hbm" # 1️⃣ 加载模型 model = HB_HBMRuntime(MODEL_PATH) model_name = model.model_names[0] print("Loaded model:", model_name) # 2️⃣ 查看输入信息 input_names = model.input_names[model_name] input_shapes = model.input_shapes[model_name] input_dtypes = model.input_dtypes[model_name] print("Input info:") for name in input_names: print(" Name:", name) print(" Shape:", input_shapes[name]) print(" Dtype:", input_dtypes[name]) # 3️⃣ 使用真实图片测试 IMAGE_DIR = "/home/sunrise/opt/dev/project/tools/images_20260316_142840" image_files = [f for f in os.listdir(IMAGE_DIR) if f.lower().endswith(".jpg")] image_files.sort() print(f"\nFound {len(image_files)} images.") for img_name in image_files: img_path = os.path.join(IMAGE_DIR, img_name) img = cv2.imread(img_path) if img is None: print(f"Skip invalid image: {img_name}") continue # ===== YOLOv8 Letterbox 预处理(保持比例)===== h0, w0 = img.shape[:2] target_size = 640 r = min(target_size / h0, target_size / w0) new_w, new_h = int(w0 * r), int(h0 * r) resized = cv2.resize(img, (new_w, new_h)) pad_w = target_size - new_w pad_h = target_size - new_h top = pad_h // 2 bottom = pad_h - top left = pad_w // 2 right = pad_w - left img_letterbox = cv2.copyMakeBorder( resized, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114) ) img_display = img_letterbox.copy() img_input_float = img_letterbox.astype(np.float32) / 255.0 input_tensors = {} for name in input_names: shape = input_shapes[name] dtype = hb_dtype_map.get(input_dtypes[name].name, np.float32) # 默认假设输入是 NCHW F32 if len(shape) == 4: # HWC -> CHW img_input = np.transpose(img_input_float, (2, 0, 1)) img_input = np.expand_dims(img_input, axis=0) img_input = img_input.astype(dtype) input_tensors[name] = img_input else: # 其他情况 fallback input_tensors[name] = np.zeros(shape, dtype=dtype) results = model.run(input_tensors) print(f"\nImage: {img_name}") for output_name, output_data in results[model_name].items(): print(" Output:", output_name, "shape:", output_data.shape) # ===== YOLOv8 解码 ===== # (1, 7, 8400) -> (8400, 7) preds = output_data[0].transpose(1, 0) boxes = preds[:, 0:4] # xywh (already decoded in export) cls_scores = preds[:, 4:] # class logits # YOLOv8 uses sigmoid (NOT softmax) cls_probs = 1.0 / (1.0 + np.exp(-cls_scores)) cls_ids = np.argmax(cls_probs, axis=1) scores = np.max(cls_probs, axis=1) # 提高置信度阈值(避免全屏框) CONF_THRESH = 0.6 # 过滤低置信度 keep_mask = scores > CONF_THRESH boxes = boxes[keep_mask] scores = scores[keep_mask] cls_ids = cls_ids[keep_mask] if len(boxes) == 0: cv2.imshow("det_result", img_display) if cv2.waitKey(1) & 0xFF == ord('q'): break continue # 转换为 xyxy xyxy_boxes = [] for b in boxes: cx, cy, w, h = b x1 = cx - w / 2 y1 = cy - h / 2 x2 = cx + w / 2 y2 = cy + h / 2 xyxy_boxes.append([x1, y1, x2 - x1, y2 - y1]) # cv2 NMSBoxes uses x,y,w,h # OpenCV NMS indices = cv2.dnn.NMSBoxes( xyxy_boxes, scores.tolist(), CONF_THRESH, 0.45 ) if len(indices) > 0: indices = indices.flatten() else: indices = [] for i in indices: cx, cy, w, h = boxes[i] x1 = int(cx - w / 2) y1 = int(cy - h / 2) x2 = int(cx + w / 2) y2 = int(cy + h / 2) cv2.rectangle(img_display, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText( img_display, f"{cls_ids[i]}:{scores[i]:.2f}", (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1 ) # ===== 视频流方式显示 ===== cv2.imshow("det_result", img_display) # 1ms 刷新,按 q 退出 if cv2.waitKey(1) & 0xFF == ord('q'): break cv2.destroyAllWindows()