(1)模型下载地址

v5 github地址: GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > TFLite

git clone https://github.com/ultralytics/yolov5.git

pip install  -r requirements.txt     -i https://pypi.tuna.tsinghua.edu.cn/simple

v6 GitHub - meituan/YOLOv6: YOLOv6: a single-stage object detection framework dedicated to industrial applications.


git clone  https://github.com/meituan/YOLOv6.git

github地址:GitHub - meituan/YOLOv6: YOLOv6: a single-stage object detection framework dedicated to industrial applications.

v7 github地址:

git clone https://github.com/WongKinYiu/yolov7.git

GitHub - WongKinYiu/yolov7: Implementation of paper - YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors

v8 github 地址: GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLite

依赖包安装

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

(2)数据集格式

v5 v8 数据格式为:

v6、v7 数据集格式为:

(3)推理测试,看模型安装是否成功

v5推理

python detect.py --weights  --source bus.jpg

v6 推理   用绝对路径,不然报错
python tools/infer.py --weights yolov6s_v4.pt --source  ./assets/image3.jpg

v7推理
python detect.py --weights yolov7.pt --conf 0.25 --img-size 640 --source inference/images/horses.jpg

v8推理
python detect.py --weights      --source bus.jpg

(4)一: data.yaml配置

v5/v8
path: path/data            #data数据集的根目录
train: train            #path 下的Train路径,  相对与path
val: val
test: test

# Classes
nc: 5  
names: ['dog', 'cat']

v5/v8数据结构
---data:
        --- train:
                ---images
                ---labels

        --- val:
                 ---images
                ---labels

        --- test:
                 ---images
                ---labels
          


v6
train: data/images/train
val: data/images/val
test: data/images/test

# Classes
nc: 5  # number of classes
names: ['dog', 'cat'] 


v7  
train: data/images/train
val: data/images/val
test: data/images/test

# Classes
nc: 5  # number of classes
names: ['dog', 'cat'] 
 
v6/7 数据集结构
---data:  
       ---images:
                ---train
                --- val
                --- test
       ---labels:
                 ---train
                --- val
                --- test

 (4)二:如果yolov6,想要和yolov5数据集格式一样,可以参考以下博客:

yolov6训练yolov5格式数据集_is an invalid directory path!-CSDN博客

 1. data.yaml 格式如下(和yolov5基本一致,最后定位到images层):

train: data/train/images
val: data/val/images
test: data/test/images

# Classes
nc: 5  # number of classes
names: ['cat', 'dog']  

2.修改yolov6\core\engine.py中48行

class Trainer:
    def __init__(self, args, cfg, device):
        self.args = args
        self.cfg = cfg
        self.device = device
 
        if args.resume:
            self.ckpt = torch.load(args.resume, map_location='cpu')
 
        self.rank = args.rank
        self.local_rank = args.local_rank
        self.world_size = args.world_size
        self.main_process = self.rank in [-1, 0]
        self.save_dir = args.save_dir
        # get data loader
        self.data_dict = load_yaml(args.data_path)
        self.num_classes = self.data_dict['nc']

        # ----------增加代码---------------------------------------------------------
        from pathlib import Path
        FILE = Path(__file__).resolve()
        ROOT = FILE.parents[1]
        path = Path(self.data_dict.get('path') or '')
        if not path.is_absolute():
            path = (ROOT / path).resolve()
        for k in 'train', 'val', 'test':
            if self.data_dict.get(k):  # prepend path
                self.data_dict[k] = str(path / self.data_dict[k]) if isinstance(self.data_dict[k], str) else [
                    str(path / x) for x in self.data_dict[k]]
         # ----------增加代码---------------------------------------------------------

 
        self.train_loader, self.val_loader = self.get_data_loader(args, cfg, self.data_dict)
        # get model and optimizer
        model = self.get_model(args, cfg, self.num_classes, device)
        if self.args.distill:
            self.teacher_model = self.get_teacher_model(args, cfg, self.num_classes, device)
        if self.args.quant:
            self.quant_setup(model, cfg, device)
        if cfg.training_mode == 'repopt':
            scales = self.load_scale_from_pretrained_models(cfg, device)
            reinit = False if cfg.model.pretrained is not None else True
            self.optimizer = RepVGGOptimizer(model, scales, args, cfg, reinit=reinit)
        else:
            self.optimizer = self.get_optimizer(args, cfg, model)
        self.scheduler, self.lf = self.get_lr_scheduler(args, cfg, self.optimizer)
        self.ema = ModelEMA(model) if self.main_process else None
        # tensorboard
        self.tblogger = SummaryWriter(self.save_dir) if self.main_process else None
        self.start_epoch = 0
        # resume
        if hasattr(self, "ckpt"):
            resume_state_dict = self.ckpt['model'].float().state_dict()  # checkpoint state_dict as FP32
            model.load_state_dict(resume_state_dict, strict=True)  # load
            self.start_epoch = self.ckpt['epoch'] + 1
            self.optimizer.load_state_dict(self.ckpt['optimizer'])
            if self.main_process:
                self.ema.ema.load_state_dict(self.ckpt['ema'].float().state_dict())
                self.ema.updates = self.ckpt['updates']
        self.model = self.parallel_model(args, model, device)
        self.model.nc, self.model.names = self.data_dict['nc'], self.data_dict['names']
 
        self.max_epoch = args.epochs
        self.max_stepnum = len(self.train_loader)
        self.batch_size = args.batch_size
        self.img_size = args.img_size
        self.vis_imgs_list = []
        self.write_trainbatch_tb = args.write_trainbatch_tb
        # set color for classnames
        self.color = [tuple(np.random.choice(range(256), size=3)) for _ in range(self.model.nc)]
 
        self.loss_num = 3
        self.loss_info = ['Epoch', 'iou_loss', 'dfl_loss', 'cls_loss']
        if self.args.distill:
            self.loss_num += 1
            self.loss_info += ['cwd_loss']

3. yolov6\data\datasets.py中的get_imgs_labels函数,大约268行,增加代码:

    def get_imgs_labels(self, img_dir):
 
        assert osp.exists(img_dir), f"{img_dir} is an invalid directory path!"
        valid_img_record = osp.join(
            osp.dirname(img_dir), "." + osp.basename(img_dir) + ".json"
        )
        NUM_THREADS = min(8, os.cpu_count())
 
        img_paths = glob.glob(osp.join(img_dir, "**/*"), recursive=True)
        img_paths = sorted(
            p for p in img_paths if p.split(".")[-1].lower() in IMG_FORMATS and os.path.isfile(p)
        )
        assert img_paths, f"No images found in {img_dir}."
 
        img_hash = self.get_hash(img_paths)
        if osp.exists(valid_img_record):
            with open(valid_img_record, "r") as f:
                cache_info = json.load(f)
                if "image_hash" in cache_info and cache_info["image_hash"] == img_hash:
                    img_info = cache_info["information"]
                else:
                    self.check_images = True
        else:
            self.check_images = True
 
        # check images
        if self.check_images and self.main_process:
            img_info = {}
            nc, msgs = 0, []  # number corrupt, messages
            LOGGER.info(
                f"{self.task}: Checking formats of images with {NUM_THREADS} process(es): "
            )
            with Pool(NUM_THREADS) as pool:
                pbar = tqdm(
                    pool.imap(TrainValDataset.check_image, img_paths),
                    total=len(img_paths),
                )
                for img_path, shape_per_img, nc_per_img, msg in pbar:
                    if nc_per_img == 0:  # not corrupted
                        img_info[img_path] = {"shape": shape_per_img}
                    nc += nc_per_img
                    if msg:
                        msgs.append(msg)
                    pbar.desc = f"{nc} image(s) corrupted"
            pbar.close()
            if msgs:
                LOGGER.info("\n".join(msgs))
 
            cache_info = {"information": img_info, "image_hash": img_hash}
            # save valid image paths.
            with open(valid_img_record, "w") as f:
                json.dump(cache_info, f)
 
        # check and load anns


        # ---------------------------------增加代码------------------------------------
        try:
            label_dir = osp.join(
                osp.dirname(osp.dirname(img_dir)), "labels", osp.basename(img_dir)
            )
            assert osp.exists(label_dir), f"{label_dir} is an invalid directory path!"
        except:
            label_dir = osp.join(
                osp.dirname(img_dir), "labels"
            )
            assert osp.exists(label_dir), f"{label_dir} is an invalid directory path!"

          # ---------------------------------增加代码------------------------------------



        # Look for labels in the save relative dir that the images are in
        def _new_rel_path_with_ext(base_path: str, full_path: str, new_ext: str):
            rel_path = osp.relpath(full_path, base_path)
            return osp.join(osp.dirname(rel_path), osp.splitext(osp.basename(rel_path))[0] + new_ext)
 
 
        img_paths = list(img_info.keys())
        label_paths = sorted(
            osp.join(label_dir, _new_rel_path_with_ext(img_dir, p, ".txt"))
            for p in img_paths
        )
        assert label_paths, f"No labels found in {label_dir}."
        label_hash = self.get_hash(label_paths)
        if "label_hash" not in cache_info or cache_info["label_hash"] != label_hash:
            self.check_labels = True
 
        if self.check_labels:
            cache_info["label_hash"] = label_hash
            nm, nf, ne, nc, msgs = 0, 0, 0, 0, []  # number corrupt, messages
            LOGGER.info(
                f"{self.task}: Checking formats of labels with {NUM_THREADS} process(es): "
            )
            with Pool(NUM_THREADS) as pool:
                pbar = pool.imap(
                    TrainValDataset.check_label_files, zip(img_paths, label_paths)
                )
                pbar = tqdm(pbar, total=len(label_paths)) if self.main_process else pbar
                for (
                    img_path,
                    labels_per_file,
                    nc_per_file,
                    nm_per_file,
                    nf_per_file,
                    ne_per_file,
                    msg,
                ) in pbar:
                    if nc_per_file == 0:
                        img_info[img_path]["labels"] = labels_per_file
                    else:
                        img_info.pop(img_path)
                    nc += nc_per_file
                    nm += nm_per_file
                    nf += nf_per_file
                    ne += ne_per_file
                    if msg:
                        msgs.append(msg)
                    if self.main_process:
                        pbar.desc = f"{nf} label(s) found, {nm} label(s) missing, {ne} label(s) empty, {nc} invalid label files"
            if self.main_process:
                pbar.close()
                with open(valid_img_record, "w") as f:
                    json.dump(cache_info, f)
            if msgs:
                LOGGER.info("\n".join(msgs))
            if nf == 0:
                LOGGER.warning(
                    f"WARNING: No labels found in {osp.dirname(img_paths[0])}. "
                )
 
        if self.task.lower() == "val":
            if self.data_dict.get("is_coco", False): # use original json file when evaluating on coco dataset.
                assert osp.exists(self.data_dict["anno_path"]), "Eval on coco dataset must provide valid path of the annotation file in config file: data/coco.yaml"
            else:
                assert (
                    self.class_names
                ), "Class names is required when converting labels to coco format for evaluating."
                save_dir = osp.join(osp.dirname(osp.dirname(img_dir)), "annotations")
                if not osp.exists(save_dir):
                    os.mkdir(save_dir)
                save_path = osp.join(
                    save_dir, "instances_" + osp.basename(img_dir) + ".json"
                )
                TrainValDataset.generate_coco_format_labels(
                    img_info, self.class_names, save_path
                )
 
        img_paths, labels = list(
            zip(
                *[
                    (
                        img_path,
                        np.array(info["labels"], dtype=np.float32)
                        if info["labels"]
                        else np.zeros((0, 5), dtype=np.float32),
                    )
                    for img_path, info in img_info.items()
                ]
            )
        )
        self.img_info = img_info
        LOGGER.info(
            f"{self.task}: Final numbers of valid images: {len(img_paths)}/ labels: {len(labels)}. "
        )
        return img_paths, labels

以上两处修改之后yolov6就可以直接使用yolov5数据集。

参考博客为:yolov6训练yolov5格式数据集_is an invalid directory path!-CSDN博客

(5)训练   

 注意:yolov6的--data 参数 ,用绝对路径,不然报错。

#v5
python train.py --weights yolov5s.pt  --data data/data.yaml  --epochs  200  --imgsz 640 
nohup python train.py --weights yolov5s.pt --data data/zf.yaml --epochs 200 --imgsz 640 > ./logs/train_oringin.log 2>&1 &

#v6
python tools/train.py  --conf-file ./configs/yolov6s.py --data-path data/data.yaml --epochs 200 --img-size 640 

#v7
python train.py  --data data/zf_v7.yaml  --cfg cfg/training/yolov7-tiny.yaml --weights 'yolov7-tiny.pt'  

#v8
python train.py

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

(6)yolov8指定不同大小的模型(n s  l m x)

  1.复制 /ultralytics/cfg/models/v8/detect/yolov8-detect.yaml 一份,重命名(一定重命名)。

修改nc 类别数, scales,不使用的规格,都注释掉。使用哪个,放开哪个。

2.yaml不重命名,scales不同的规格也不用注释,则需要修改yolov8.yaml后缀,例如:使用s,则修改为yolov8s.yaml。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐