(篇三)基于PyDracula搭建一个深度学习的软件之解析yolo算法融合

在前面两篇中,篇一介绍了启动界面的制作篇二介绍了如何修改PyDracula的界面,那么这一篇我们学习一下yolo要融合进入软件中,需要了解的两个类。

1YoloPredictor类——检测器

class YoloPredictor(BasePredictor, QObject):
    # 定义信号,传递不同类型的数据给GUI或其他部分
    yolo2main_pre_img = Signal(np.ndarray)  # 原始图像信号(图像数据类型为NumPy数组)
    yolo2main_res_img = Signal(np.ndarray)  # 测试结果图像信号(图像数据类型为NumPy数组)
    yolo2main_status_msg = Signal(str)  # 状态消息信号(如:检测中、暂停、停止、错误等)
    yolo2main_fps = Signal(str)  # FPS(帧率)信号(类型为字符串,显示每秒处理的帧数)
    yolo2main_labels = Signal(dict)  # 检测到的目标类别及其数量(字典类型)
    yolo2main_progress = Signal(int)  # 检测进度信号(表示任务完成的进度百分比)
    yolo2main_class_num = Signal(int)  # 检测到的类别数量信号(整数类型)
    yolo2main_target_num = Signal(int)  # 检测到的目标数量信号(整数类型)

    def __init__(self, cfg=DEFAULT_CFG, overrides=None):
        super(YoloPredictor, self).__init__()  # 调用父类BasePredictor的构造函数进行初始化
        QObject.__init__(self)  # 初始化QObject,支持信号和槽机制
        self.args = get_cfg(cfg, overrides)  # 获取配置信息,最终会从这里获取DEFAULT_CFG_PATH = ROOT / 'yolo/cfg/default.yaml'
        ''''下面这个配置信息是为了填补yaml文件的空白'''
        # 设置项目路径:如果args.project为空,则使用默认路径并加上任务名称
        project = self.args.project or Path(SETTINGS['runs_dir']) / self.args.task
        # 设置模型名称:根据模式(mode)命名
        name = f'{
     self.args.mode}'
        # 设置保存目录:调用increment_path以避免覆盖现有文件夹
        self.save_dir = increment_path(Path(project) / name, exist_ok=self.args.exist_ok)
        self.done_warmup = False  # 标记是否完成预热阶段(如:模型加载、预处理等)

        if self.args.show:
            self.args.show = check_imshow(warn=True)  # 如果需要显示图像,则检查imshow是否可用

        # GUI相关参数初始化
        self.used_model_name = None  # 当前使用的模型名称
        self.new_model_name = None  # 实时更新的模型名称
        self.source = ''  # 输入源路径(如视频、图像路径)
        self.stop_dtc = False  # 停止检测标志
        self.continue_dtc = True  # 是否继续检测(用于暂停检测)
        self.save_res = False  # 是否保存测试结果
        self.save_txt = False  # 是否保存标签文件(txt格式)
        self.iou_thres = 0.45  # IoU阈值(用于判断是否为目标)
        self.conf_thres = 0.25  # 置信度阈值(检测到目标的置信度要求)
        self.speed_thres = 10  # 延迟阈值,单位毫秒(检测的最大延迟时间)
        self.labels_dict = {
   }  # 存储检测结果的字典(类别名和数量)
        self.progress_value = 0  # 进度条的当前进度(0-100)

        # 以下为后续任务需要的变量初始化
        self.model = None  # 存储YOLO检测模型
        self.data = self.args.data  # 存储数据字典(包含数据集路径等)
        self.imgsz = None  # 输入图像的大小(例如:640x640)
        self.device = None  # 设备(GPU或CPU)
        self.dataset = None  # 数据集对象
        self.vid_path, self.vid_writer = None, None  # 存储视频路径和视频写入器(如果需要处理视频)
        self.annotator = None  # 注释器对象(用于图像标注)
        self.data_path = None  # 数据路径(用于加载数据)
        self.source_type = None  # 输入源类型(视频、图像等)
        self.batch = None  # 批次大小(用于批处理预测)

        # 添加回调函数(用于处理检测过程中的各种操作)
        self.callbacks = defaultdict(list, callbacks.default_callbacks)  # 默认为空列表的回调字典
        callbacks.add_integration_callbacks(self)  # 将回调集成到当前对象中

    # 主函数用于目标检测
    @smart_inference_mode()  # 装饰器,可能用于切换推理模式(例如加速或禁用某些操作)
    def run(self):
        try:
            # 如果开启详细模式,则输出空行日志
            if self.args.verbose:
                LOGGER.info('')

            # 设置模型
            self.yolo2main_status_msg.emit('Loding Model...')  # 向主界面发射模型加载的状态信息
            if not self.model:  # 如果没有已加载模型
                self.setup_model(self.new_model_name)  # 初始化并加载新模型
                self.used_model_name = self.new_model_name  # 设置当前使用的模型名称

            # 设置输入源
            self.setup_source(self.source if self.source is not None else self.args.source)

            # 检查保存路径/标签文件夹
            if self.save_res or self.save_txt:  # 如果需要保存结果或标签
                (self.save_dir / 'labels' if self.save_txt else self.save_dir).mkdir(parents=True, exist_ok=True)

            # 热身模型
            if not self.done_warmup:  # 如果模型未热身
                self.model.warmup(imgsz=(1 if self.model.pt or self.model.triton else self.dataset.bs, 3, *self.imgsz))
                self.done_warmup = True  # 设置热身完成标志

            # 初始化状态变量
            self.seen, self.windows, self.dt, self.batch = 0, [], (ops.Profile(), ops.Profile(), ops.Profile()), None

            # 开始目标检测
            count = 0  # 当前帧数
            start_time = time.time()  # 用于计算帧率的开始时间
            batch = iter(self.dataset)  # 将数据集转化为迭代器

            while True:
                # 检查是否终止检测
                if self.stop_dtc:
                    if isinstance(self.vid_writer[-1], cv2.VideoWriter):
                        self.vid_writer[-1].release()  # 释放视频写入器
                    self.yolo2main_status_msg.emit('Detection terminated!')  # 向主界面发射终止信息
                    break

                # 检查是否需要切换模型
                if self.used_model_name != self.new_model_name:
                    self.setup_model(self.new_model_name)  # 加载新的模型
                    self.used_model_name = self.new_model_name  # 更新当前使用的模型名称

                # 检查是否暂停检测
                if self.continue_dtc:
                    self.yolo2main_status_msg.emit('Detecting...')  # 向主界面发射“正在检测”信息
                    batch = next(self.dataset)  # 获取下一批数据

                    self.batch = batch  # 保存当前批次
                    path, im, im0s, vid_cap, s = batch  # 从批次中提取路径、图像、原始图像、视频捕获和其他信息
                    visualize = increment_path(self.save_dir / Path(path).stem,
                                               mkdir=True) if self.args.visualize else False  # 是否可视化

                    # 计算进度和帧率(待优化)
                    count += 1  # 帧计数加1
                    if vid_cap:
                        all_count = vid_cap.get(cv2.CAP_PROP_FRAME_COUNT)  # 获取视频总帧数
                    else:
                        all_count = 1  # 如果不是视频,则设置总帧数为1
                    self.progress_value = int(count / all_count * 1000)  # 更新进度条(0~1000)
                    if count % 5 == 0 and count >= 5:  # 每5帧计算一次帧率
                        self.yolo2main_fps.emit(str(int(5 / (time.time() - start_time))))  # 向主界面发射每秒帧率
                        start_time = time.time()  # 重置开始时间

                    # 预处理图像
                    with self.dt[0]:
                        im = self.preprocess(im)  # 预处理图像
                        if len(im.shape) == 3:  # 如果图像维度为3,则扩展批次维度
                            im = im[None]  # 扩展为批次维度
                    # 推理过程
                    with self.dt[1]:
                        preds = self.model(im, augment=self.args.augment, visualize=visualize)  # 进行推理
                    # 后处理
                    with self.dt[2]:
                        self.results = self.postprocess(preds, im, im0s)  # 后处理推理结果

                    # 可视化、保存和写入结果
                    n = len(im)  # 图像数量(通常是1,除非是批次推理)
                    for i in range(n):
                        # 保存速度信息
                        self.results[i].speed = {
   
                            'preprocess': self.dt[0].dt * 1E3 / n,
                            'inference': self.dt[1].dt * 1E3 / n,
                            'postprocess': self.dt[2].dt * 1E3 / n}
                        p, im0 = (path[i], im0s[i].copy()) if self.source_type.webcam or self.source_type.from_img \
                            else (path, im0s.copy())  # 设置路径
                        p = Path(p)  # 转换路径为Path对象

                        # 获取检测框和标签
                        label_str = self.write_results(i, self.results, (p, im, im0))  # 获取标签字符串

                        # 处理标签和目标数量
                        class_nums = 0  # 类别数
                        target_nums = 0  # 目标数
                        self.labels_dict = {
   }  # 标签字典
                        if 'no detections' in label_str:  # 如果没有检测到目标
                            pass
                        else:
                            # 解析标签字符串,更新目标和类别数量
                            for ii in label_str.split
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又又土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值