Files
opi-yolo/infer_camera_direct.py
T
2026-05-25 14:56:48 +08:00

158 lines
5.5 KiB
Python

import os
import cv2
import numpy as np
import time
from ais_bench.infer.interface import InferSession
# ==================== 硬编码配置区域 ====================
MODEL_PATH = "./yolo26_8t.om" # 你的 YOLO26 模型路径
CONF_THRESHOLD = 0.25 # 置信度过滤阈值 (YOLO26 推荐 0.25)
CAMERA_INDEX = 0 # 摄像头索引 (默认0,如果打不开可以尝试1或2)
# ========================================================
class YOLO26CameraInfer:
def __init__(self, model_path, device_id=0):
self.device_id = device_id
self.model_path = model_path
# 自动检查模型文件是否存在,防止硬编码路径写错导致程序崩溃
if not os.path.exists(model_path):
raise FileNotFoundError(f"找不到硬编码的模型文件: {model_path},请检查路径是否正确。")
# 创建 ais_bench 推理会话
self.session = InferSession(device_id, model_path)
self.input_width = 640
self.input_height = 640
def letterbox(self, img, new_shape=(640, 640), color=(114, 114, 114)):
shape = img.shape[:2]
r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
new_unpad = (int(round(shape[1] * r)), int(round(shape[0] * r)))
dw = new_shape[1] - new_unpad[0]
dh = new_shape[0] - new_unpad[1]
left = dw // 2
right = dw - left
top = dh // 2
bottom = dh - top
if shape[::-1] != new_unpad:
img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)
img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
return img, r, (left, top)
def preprocess_frame(self, img_bgr):
self.original_height, self.original_width = img_bgr.shape[:2]
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
img_resized, self.ratio, (self.pad_left, self.pad_top) = self.letterbox(
img_rgb, (self.input_width, self.input_height)
)
img_input = (img_resized.astype(np.float32) / 255.0).astype(np.float32)
img_input = np.ascontiguousarray(np.transpose(img_input, (2, 0, 1))[np.newaxis, :, :, :])
return img_input
def infer(self, img_input):
return self.session.infer([img_input])
def postprocess(self, infer_result, conf_threshold):
detections = []
if isinstance(infer_result, (list, tuple)):
output = infer_result[0]
else:
output = infer_result
if output.ndim == 3:
output = output[0]
for det in output:
confidence = det[4]
if confidence < conf_threshold:
continue
x1_scale, y1_scale, x2_scale, y2_scale = det[0], det[1], det[2], det[3]
cls_id = int(det[5])
x1 = (x1_scale - self.pad_left) / self.ratio
y1 = (y1_scale - self.pad_top) / self.ratio
x2 = (x2_scale - self.pad_left) / self.ratio
y2 = (y2_scale - self.pad_top) / self.ratio
x1 = max(0, min(x1, self.original_width))
y1 = max(0, min(y1, self.original_height))
x2 = max(0, min(x2, self.original_width))
y2 = max(0, min(y2, self.original_height))
detections.append([x1, y1, x2, y2, confidence, cls_id])
return detections
def draw_boxes(image, detections):
for det in detections:
x1, y1, x2, y2, conf, cls_id = det
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
label = f"Class: {cls_id} {conf:.2f}"
(label_w, label_h), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
cv2.rectangle(image, (x1, y1 - label_h - 5), (x1 + label_w, y1), (0, 255, 0), -1)
cv2.putText(image, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
return image
if __name__ == "__main__":
print("正在初始化 YOLOv26 离线推理引擎...")
# 传入硬编码的模型路径
yolo_infer = YOLO26CameraInfer(MODEL_PATH)
# 打开硬编码指定的摄像头
cap = cv2.VideoCapture(CAMERA_INDEX)
if not cap.isOpened():
print(f"错误:无法打开摄像头索引 {CAMERA_INDEX},请检查物理连接。")
exit()
# 尝试设置合适的分辨率
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
print(f"初始化成功!当前模型:{MODEL_PATH} | 过滤阈值:{CONF_THRESHOLD}")
print("开始实时检测,在画面窗口按下 'q' 键可退出...")
fps_start_time = 0
while True:
ret, frame = cap.read()
if not ret:
continue
# 预处理与 NPU 推理
input_tensor = yolo_infer.preprocess_frame(frame)
raw_result = yolo_infer.infer(input_tensor)
# 后处理(使用硬编码的置信度)
detections = yolo_infer.postprocess(raw_result, conf_threshold=CONF_THRESHOLD)
# 绘制结果
frame = draw_boxes(frame, detections)
# FPS 实时计算与显示
fps_end_time = time.time()
time_diff = fps_end_time - fps_start_time
fps = 1 / time_diff if time_diff > 0 else 0
fps_start_time = fps_end_time
cv2.putText(frame, f"FPS: {fps:.1f}", (20, 40),
cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2)
cv2.imshow("YOLOv26 Real-time Detection", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
print("检测已结束。")