yolov8的predict使用方法,更改predict.py的输出结果,输出label的真实坐标,保存图片和txt文档,图片中没有异物生成空的txt文档

本文介绍了如何在Yolov8中使用predict函数进行图像预测,包括修改默认输出格式为真实坐标、处理无异物情况下生成空txt文件以及实时流式预测的代码调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Yolov8的predict的使用方法:

新建predict.py如下:

from ultralytics import YOLO


model = YOLO("你训练好的模型.pt")
model.predict(source="datasets/images/val",save=True,save_conf=True,save_txt=True,name='output')

#source后为要预测的图片数据集的的路径
#save=True为保存预测结果
#save_conf=True为保存坐标信息
#save_txt=True为保存txt结果,但是yolov8本身当图片中预测不到异物时,不产生txt文件

默认predict的输出坐标为xywh格式,即中心点坐标和预测的框的宽高,将其改为真实坐标方法如下:在ultralytics\engine\results.py中,将def save_txt()置换为如下代码:

def save_txt(self, txt_file, save_conf=False):
        """
        Save predictions into txt file.

        Args:
            txt_file (str): txt file path.
            save_conf (bool): save confidence score or not.
        """
        boxes = self.boxes
        masks = self.masks
        probs = self.probs
        kpts = self.keypoints
        texts = []
        if probs is not None:
            # Classify
            [texts.append(f'{probs.data[j]:.2f} {self.names[j]}') for j in probs.top5]
        elif boxes:
            # Detect/segment/pose
            for j, d in enumerate(boxes):
                c, conf, id = int(d.cls), float(d.conf), None if d.id is None else int(d.id.item())
                #line = (c, *d.xywhn.view(-1))
                line = ( c,conf, *d.xyxy.view(-1))  #重点在这里,还可以通过这里改变txt中信息#的顺序
                if masks:
                    seg = masks[j].xyn[0].copy().reshape(-1)  # reversed mask.xyn, (n,2) to (n*2)
                    line = (c, *seg)
                if kpts is not None:
                    kpt = torch.cat((kpts[j].xyn, kpts[j].conf[..., None]), 2) if kpts[j].has_visible else kpts[j].xyn
                    line += (*kpt.reshape(-1).tolist(), )
                line += (conf, ) * save_conf + (() if id is None else (id, ))
                line = line[:-1]
                texts.append('%s %.6f %d %d %d %d' % (line[0], float(line[1]), int(line[2]), int(line[3]), int(line[4]), int(line[5])))

        if texts:
            Path(txt_file).parent.mkdir(parents=True, exist_ok=True)  # make directory
            with open(txt_file, 'a') as f:
                f.writelines(text + '\n' for text in texts)

要实现图片中没有异物生成空的txt文档,采用如下方法:

在ultralytics\engine\predictor.py中,找到def stream_inference(),将其置换为如下代码:

def stream_inference(self, source=None, model=None, *args, **kwargs):
        """Streams real-time inference on camera feed and saves results to file."""
        if self.args.verbose:
            LOGGER.info('')

        # Setup model
        if not self.model:
            self.setup_model(model)

        # Setup source every time predict is called
        self.setup_source(source if source is not None else self.args.source)

        # Check if save_dir/ label file exists
        if self.args.save or self.args.save_txt:
            (self.save_dir / 'labels' if self.args.save_txt else self.save_dir).mkdir(parents=True, exist_ok=True)

        # Warmup model
        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.batch, profilers = 0, [], None, (ops.Profile(), ops.Profile(), ops.Profile())
        self.run_callbacks('on_predict_start')
        for batch in self.dataset:
            self.run_callbacks('on_predict_batch_start')
            self.batch = batch
            path, im0s, vid_cap, s = batch

            # Preprocess
            with profilers[0]:
                im = self.preprocess(im0s)

            # Inference
            with profilers[1]:
                preds = self.inference(im, *args, **kwargs)

            # Postprocess
            with profilers[2]:
                self.results = self.postprocess(preds, im, im0s)
            self.run_callbacks('on_predict_postprocess_end')

            # Visualize, save, write results
            n = len(im0s)
            for i in range(n):
                self.seen += 1
                self.results[i].speed = {
                    'preprocess': profilers[0].dt * 1E3 / n,
                    'inference': profilers[1].dt * 1E3 / n,
                    'postprocess': profilers[2].dt * 1E3 / n}
                p, im0 = path[i], None if self.source_type.tensor else im0s[i].copy()
                p = Path(p)

                if self.args.verbose or self.args.save or self.args.save_txt or self.args.show:
                    s += self.write_results(i, self.results, (p, im, im0))
                if self.args.save or self.args.save_txt:
                    self.results[i].save_dir = self.save_dir.__str__()
                if self.args.show and self.plotted_img is not None:
                    self.show(p)
                if self.args.save and self.plotted_img is not None:
                    self.save_preds(vid_cap, i, str(self.save_dir / p.name))

            self.run_callbacks('on_predict_batch_end')
            yield from self.results

            # Print time (inference-only)
            if self.args.verbose:
                LOGGER.info(f'{s}{profilers[1].dt * 1E3:.1f}ms')

        # Release assets
        if isinstance(self.vid_writer[-1], cv2.VideoWriter):
            self.vid_writer[-1].release()  # release final video writer

        # Print results
        if self.args.verbose and self.seen:
            t = tuple(x.t / self.seen * 1E3 for x in profilers)  # speeds per image
            LOGGER.info(f'Speed: %.1fms preprocess, %.1fms inference, %.1fms postprocess per image at shape '
                        f'{(1, 3, *im.shape[2:])}' % t)
        if self.args.save or self.args.save_txt or self.args.save_crop:
            nl = len(list(self.save_dir.glob('labels/*.txt')))  # number of labels
            s = f"\n{nl} label{'s' * (nl > 1)} saved to {self.save_dir / 'labels'}" if self.args.save_txt else ''
            m = f"\n{nl} image{'s' * (nl > 1)} saved to {self.save_dir / 'images'}" if self.args.save_txt else ''
            LOGGER.info(f"Results saved to {colorstr('bold', self.save_dir)}")
            # 原始文件夹路径和目标文件夹路径
        source_folder = self.save_dir
        target_folder = os.path.join(source_folder, 'images')
        target_label_folder = os.path.join(source_folder, 'labels')

        # 创建目标文件夹
        os.makedirs(target_folder, exist_ok=True)

        # 获取原始文件夹中的所有文件
        files = os.listdir(source_folder)

        # 遍历所有文件
        for file in files:
            # 构建文件的绝对路径
            file_path = os.path.join(source_folder, file)
            
            # 检查文件是否是图片文件
            if os.path.isfile(file_path) and file.lower().endswith(('.jpg', '.jpeg', '.png')):
                # 构建目标文件的路径
                target_file_path = os.path.join(target_folder, file)
                
                # 将图片文件复制到目标文件夹
                shutil.copy(file_path, target_file_path)
                
                # 删除原始文件夹中的图片文件
                os.remove(file_path)

        image_folder =  target_folder
        txt_folder = target_label_folder
        image_files = [file for file in os.listdir(image_folder) if file.lower().endswith(('.jpg', '.jpeg', '.png'))]
        # 遍历图片文件夹中的图片文件
        for image_file in image_files:
        # 构建图片和txt文件的路径
            image_file_path = os.path.join(image_folder, image_file)
            txt_file_path = os.path.join(txt_folder, os.path.splitext(image_file)[0] + '.txt')

        # 检查txt文件是否已存在
            if os.path.isfile(txt_file_path):
            #print(f"txt文件'{txt_file_path}'已存在,不执行操作。")
                pass
            else:
            # 创建空白的txt文件
                with open(txt_file_path, 'w') as txt_file:
                    pass


        self.run_callbacks('on_predict_end')

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值