前几天美团发布了自己的目标检测网络,并命名为Yolov6,看来底气很足,效果上据说精度和速度比yolov5好了不少,但是可能由于是刚发布,所以很多问题和BUG存在,主要在漏检问题上吐槽的比较多,我想应该社区建立起来之后,维护团队会解决这些问题,先体验一下吧。
- conda create --name yolov6 python=3.7
- conda activate yolov6
- git clone https://github.com/meituan/YOLOv6
- cd YOLOv6
- pip install -r requirements.txt
非常顺利:

- wget https://github.com/meituan/YOLOv6/releases/download/0.1.0/yolov6s.pt
- # 下边推理命令source源和yolov5一样支持图片和图片文件夹路径
- python tools/infer.py --weights yolov6s.pt --source images --device cpu
可以看到我用cpu执行的推理,用显卡推理报了一个错:
RuntimeError: CUDA error: no kernel image is available for execution on the device
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
【故障诊断】【Ubuntu服务器】NVIDIA GeForce RTX 3090 with CUDA capability sm_86 is not compatible with the curre_鲤鱼王的成长之路的博客-CSDN博客这个博文说的和我的情况一样,cuda和torch版本不对,因此到torch管网 Start Locally | PyTorch
找了下载命令,重新调整了torch版本:

效果:

准备自己的训练集,依旧是labelimg标注,标注完的目录如下:

然后用这个脚本将voc(xml) 这种格式的数据转为yolo所需要的格式,并一块切分了数据集,脚本voc_to_yolo.py 如下:
- import xml.etree.ElementTree as ET
- import pickle
- import os
- from os import listdir, getcwd
- from os.path import join
- import random
- from shutil import copyfile
-
- classes = ['invalid', 'positive', 'negative']
- # classes=["ball"]
-
- TRAIN_RATIO = 80
-
-
- def clear_hidden_files(path):
- dir_list = os.listdir(path)
- for i in dir_list:
- abspath = os.path.join(os.path.abspath(path), i)
- if os.path.isfile(abspath):
- if i.startswith("._"):
- os.remove(abspath)
- else:
- clear_hidden_files(abspath)
-
-
- def convert(size, box):
- dw = 1. / size[0]
- dh = 1. / size[1]
- x = (box[0] + box[1]) / 2.0
- y = (box[2] + box[3]) / 2.0
- w = box[1] - box[0]
- h = box[3] - box[2]
- x = x * dw
- w = w * dw
- y = y * dh
- h = h * dh
- return (x, y, w, h)
-
-
- def convert_annotation(image_id):
- in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' % image_id)
- out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' % image_id, 'w')
- tree = ET.parse(in_file)
- root = tree.getroot()
- size = root.find('size')
- w = int(size.find('width').text)
- h = int(size.find('height').text)
-
- for obj in root.iter('object'):
- difficult = obj.find('difficult').text
- cls = obj.find('name').text
- if cls not in classes or int(difficult) == 1:
- continue
- cls_id = classes.index(cls)
- xmlbox = obj.find('bndbox')
- b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
- float(xmlbox.find('ymax').text))
- bb = convert((w, h), b)
- out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
- in_file.close()
- out_file.close()
-
-
- wd = os.getcwd()
- wd = os.getcwd()
- data_base_dir = os.path.join(wd, "VOCdevkit/")
- if not os.path.isdir(data_base_dir):
- os.mkdir(data_base_dir)
- work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
- if not os.path.isdir(work_sapce_dir):
- os.mkdir(work_sapce_dir)
- annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
- if not os.path.isdir(annotation_dir):
- os.mkdir(annotation_dir)
- clear_hidden_files(annotation_dir)
- image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
- if not os.path.isdir(image_dir):
- os.mkdir(image_dir)
- clear_hidden_files(image_dir)
- yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
- if not os.path.isdir(yolo_labels_dir):
- os.mkdir(yolo_labels_dir)
- clear_hidden_files(yolo_labels_dir)
- yolov5_images_dir = os.path.join(data_base_dir, "images/")
- if not os.path.isdir(yolov5_images_dir):
- os.mkdir(yolov5_images_dir)
- clear_hidden_files(yolov5_images_dir)
- yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
- if not os.path.isdir(yolov5_labels_dir):
- os.mkdir(yolov5_labels_dir)
- clear_hidden_files(yolov5_labels_dir)
- yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
- if not os.path.isdir(yolov5_images_train_dir):
- os.mkdir(yolov5_images_train_dir)
- clear_hidden_files(yolov5_images_train_dir)
- yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
- if not os.path.isdir(yolov5_images_test_dir):
- os.mkdir(yolov5_images_test_dir)
- clear_hidden_files(yolov5_images_test_dir)
- yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
- if not os.path.isdir(yolov5_labels_train_dir):
- os.mkdir(yolov5_labels_train_dir)
- clear_hidden_files(yolov5_labels_train_dir)
- yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
- if not os.path.isdir(yolov5_labels_test_dir):
- os.mkdir(yolov5_labels_test_dir)
- clear_hidden_files(yolov5_labels_test_dir)
-
- train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
- test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
- train_file.close()
- test_file.close()
- train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
- test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
- list_imgs = os.listdir(image_dir) # list image files
- prob = random.randint(1, 100)
- print("Probability: %d" % prob)
- for i in range(0, len(list_imgs)):
- path = os.path.join(image_dir, list_imgs[i])
- if os.path.isfile(path):
- image_path = image_dir + list_imgs[i]
- voc_path = list_imgs[i]
- (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
- (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
- annotation_name = nameWithoutExtention + '.xml'
- annotation_path = os.path.join(annotation_dir, annotation_name)
- label_name = nameWithoutExtention + '.txt'
- label_path = os.path.join(yolo_labels_dir, label_name)
- prob = random.randint(1, 100)
- print("Probability: %d" % prob)
- if (prob < TRAIN_RATIO): # train dataset
- if os.path.exists(annotation_path):
- train_file.write(image_path + '\n')
- convert_annotation(nameWithoutExtention) # convert label
- copyfile(image_path, yolov5_images_train_dir + voc_path)
- copyfile(label_path, yolov5_labels_train_dir + label_name)
- else: # test dataset
- if os.path.exists(annotation_path):
- test_file.write(image_path + '\n')
- convert_annotation(nameWithoutExtention) # convert label
- copyfile(image_path, yolov5_images_test_dir + voc_path)
- copyfile(label_path, yolov5_labels_test_dir + label_name)
- train_file.close()
- test_file.close()
转换完后的目录:

注意匹配自己标注类别,确定训练集和验证集的比例:

然后data目录下创建自己的yaml文件,依然要匹配自己的nc类别数,类别名称集合,和数据集位置:

然后下载一个预训练模型,我用yolov6s.pt,然后开始训练:
python train.py --img 640 --batch 32 --epoch 300 --data ./data/myvoc.yaml --cfg ./models/yolov5s.yaml --weights yolov5s.pt --workers 0

由于服务器并没有可视化界面,因此需要服务器先启动tensorboard服务,然后本地远程服务器,映射出来服务端口,就可以在本地访问了:
- #本地终端登陆远程服务器
- # -p 端口一般不用写,默认是22,但是有时候被修改成其他端口了需要加上-p
- ssh -L 10086:127.0.0.1:8080 username@192.168.6.55 -p 31196
-
- #远程服务器中找到tensorboard所在目录并运行
- tensorboard --logdir ./runs --port 8080
-
- #在本地浏览器中输入如下地址即可查看tensorboard结果
- http://127.0.0.1:10086
我第一次训练yolov6,map几乎为0,原因待续
第一步准备数据集的方式yolov5也适用,另一种方式:labelimg制作VOC数据集并用yolov5训练目标检测模型_RayChiu_Labloy的博客-CSDN博客_labelimg yolov5