You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用YOLOv8调用笔记本摄像头做目标检测时,窗口无法弹出

问题诊断与修复方案

核心问题分析

  1. Results对象迭代错误:YOLOv8调用model(frame)返回的是单个Results实例,而非可迭代列表,原代码中for result in results会触发迭代错误,直接导致程序终止。
  2. 断言过于严苛:assert ret会在单帧读取失败时直接崩溃程序,而摄像头偶尔读取失败属于正常情况。
  3. 冗余逻辑混乱:原代码先尝试提取person类检测结果,但最终可视化又使用全部检测数据,逻辑冗余且无意义。

修正后的代码

import torch
import numpy as np
import cv2
from time import time
from ultralytics import YOLO
import supervision as sv

class ObjectDetection:
    def __init__(self, capture_index):
        self.capture_index = capture_index
        self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
        print("Using Device: ", self.device)
        self.model = self.load_model()
        self.CLASS_NAMES_DICT = self.model.names  # 简化属性访问路径
        self.box_annotator = sv.BoxAnnotator(sv.ColorPalette.default(), thickness=3, text_thickness=3, text_scale=1.5)

    def load_model(self):
        model = YOLO("yolov8m.pt")
        model.fuse()
        return model

    def predict(self, frame):
        # 显式指定推理设备,确保计算资源正确利用
        results = self.model(frame, device=self.device)
        return results

    def plot_bboxes(self, results, frame):
        # 无检测结果时直接返回原帧
        if not results[0].boxes:
            return frame
        
        detections = sv.Detections(
            xyxy=results[0].boxes.xyxy.cpu().numpy(),
            confidence=results[0].boxes.conf.cpu().numpy(),
            class_id=results[0].boxes.cls.cpu().numpy().astype(int),
        )
        
        # 可选:仅保留person类检测结果(class_id=0对应person)
        detections = detections[detections.class_id == 0]
        
        self.labels = [f"{self.CLASS_NAMES_DICT[class_id]} {confidence:0.2f}"
                       for _, confidence, class_id, _ in detections]
        
        frame = self.box_annotator.annotate(scene=frame, detections=detections, labels=self.labels)
        return frame

    def __call__(self):
        cap = cv2.VideoCapture(self.capture_index)
        # 替换断言为友好的错误提示
        if not cap.isOpened():
            print("无法打开摄像头,请检查设备索引或权限设置")
            return
        
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
      
        while True:
            start_time = time()
            ret, frame = cap.read()
            
            # 跳过读取失败的帧,而非直接崩溃
            if not ret:
                print("读取帧失败,即将退出")
                break
            
            results = self.predict(frame)
            frame = self.plot_bboxes(results, frame)
            
            end_time = time()
            fps = 1/np.round(end_time - start_time, 2)
             
            cv2.putText(frame, f'FPS: {int(fps)}', (20,70), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0,255,0), 2)
            
            cv2.imshow('YOLOv8 Detection', frame)
 
            # 缩短等待时间,确保窗口正常刷新
            if cv2.waitKey(1) & 0xFF == 27:
                break
        
        cap.release()
        cv2.destroyAllWindows()  # 退出时销毁所有窗口,避免资源残留

detector = ObjectDetection(capture_index=0)
detector()

关键修改说明

  • 修复迭代错误:直接通过results[0]访问检测结果,避免错误遍历。
  • 添加容错处理:摄像头打开失败或帧读取失败时,输出提示并优雅退出,而非强制崩溃。
  • 简化检测逻辑:保留可选的person类过滤,同时确保可视化逻辑统一。
  • 完善资源释放:退出时调用cv2.destroyAllWindows(),避免窗口资源残留。
  • 指定推理设备:显式传入device=self.device,确保模型使用正确的计算设备。

额外排查建议

  • 检查摄像头权限:Windows需在隐私设置中授权Python访问摄像头,Linux需将用户添加到video组。
  • 降低分辨率:若设备性能不足,可将摄像头分辨率调低至640x480,减少推理负载。
  • 更新依赖库:确保ultralytics、supervision、opencv-python为最新版本,避免版本兼容问题。

内容的提问来源于stack exchange,提问作者Hamza Hussain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 07:07:56