Yolov8建立在Yolo系列历史版本的基础上,并引入了新的功能和改进点,以进一步提升性能和灵活性。Yolov8具有以下特点:
目标检测是计算机视觉中的一个重要任务,旨在识别图像或视频中的物体并确定它们的位置。有许多目标检测算法,其中一些是经典的方法,而另一些是基于深度学习的最新方法。常见的目标检测算法:
R-CNN系列(R-CNN、Fast R-CNN、Faster R-CNN):
YOLO系列(YOLO、YOLOv2、YOLOv3、YOLOv4、YOLOv5):
SSD(Single Shot MultiBox Detector):
RetinaNet:
EfficientDet:
Mask R-CNN:
这些算法具有各自的特点和适用场景,选择合适的算法通常取决于具体的应用需求、计算资源以及性能要求。深度学习方法在目标检测领域取得了显著的进展,但也有一些经典的非深度学习方法在特定情境下仍然具有优势。
YOLOv8 的主要具有以下特点:
YOLOv8 还高效灵活地支持多种导出格式,并且可在 CPU 和 GPU 上运行该模型。YOLOv8 的整体架构如下图所示:
YOLOv8是一种无锚(Anchor-Free)模型,这意味着它直接预测对象的中心,而不是通过预测锚框的偏移量来定位对象。相对于使用锚框的传统方法,无锚模型通过减少需要预测的边界框的数量,加速了复杂的推理步骤,如非极大值抑制(NMS)。
YOLOv8系列包含5个模型,其中YOLOv8 Nano(YOLOv8n)是最小且速度最快的模型,而YOLOv8 Extra Large(YOLOv8x)则是最准确但速度较慢的模型。这种层次结构允许用户在速度和准确性之间做出权衡,选择适合其特定需求的模型。
yolov8有两种安装方式,一种可直接安装U神的库,为了方便管理,还是在conda里面安装:
conda create -n yolov8 python=3.8
activate ylolv8
pip install ultralytics
源码安装时,要单独安装torch,要不然训练的时候,有可能用不了GPU,我的环境是cuda 11.7。
#新建虚拟环境
conda create -n yolov8 python=3.8
#激活
conda activate yolov8
#安装torch,
conda install pytorch==2.0.0 torchvision==0.15.0 torchaudio==2.0.0 pytorch-cuda=11.7 -c pytorch -c nvidia
#下载源码
git clone https://github.com/ultralytics/ultralytics.git
cd ultralytics
#将requirements.txt中torch torchbision 注释掉,下载其他包
pip install -r requirements.txt
安装完成之后,验证是否安装成功。
yolo task=segment mode=predict model=yolov8s-seg.pt source='1.jpg' show=True
1.OMP: Error #15: Initializing libomp.dylib, but found libiomp5.dylib already initialize
如果在训练时出现这个错误,要么就降低numpy的版本,要么就是python的版本太高,降到3.9以下就可以了。
数据采集是深度学习和人工智能任务中至关重要的一步,它为模型提供了必要的训练样本和测试数据。在实际应用中,数据采集的方法多种多样,每种方法都有其独特的优势和适用场景。以下是一些常见的数据采集方法:
使用开源已标记数据集:
爬取数据集:
自己拍摄数据集:
使用数据增强生成数据集:
众包数据标注:
合成数据集:
在数据采集过程中,确保数据的质量和多样性非常重要。同时,对于敏感信息的数据,需要遵循隐私法规,并采取相应的保护措施。综合使用多种数据采集方法,根据任务和需求选择最适合的方法,有助于建立高质量、多样性且具代表性的数据集,提高模型的性能和泛化能力。
LabelMe 是一种流行的开源图像标注工具,用于创建包含各种标注,如边界框、多边形、线条和点的标记的图像数据集。LabelMe进行标注的一般步骤:
安装LabelMe:
启动LabelMe:
labelme
或者使用图形用户界面(GUI)。创建新项目或打开现有项目:
标注对象:
保存标注:
导出标注数据:
数据集管理:
LabelMe的灵活性和易用性使其成为图像标注领域的一种流行选择。它适用于各种项目,包括目标检测、实例分割、图像分类等。在使用LabelMe进行标注时,确保按照项目需求设置合适的类别、名称和颜色,以便后续的数据处理和模型训练。
将LabelMe标注生成的JSON文件转换为YOLO格式的TXT文件需要进行一些数据格式的映射和坐标的转换。以下是一般的步骤:
{
"version": "5.3.0a0",
"flags": {},
"shapes": [
{
"label": "person",
"points": [
[
55.59312320916908,
1.6332378223495834
],
[
191.40974212034385,
258.36676217765046
]
],
"group_id": null,
"description": "",
"shape_type": "rectangle",
"flags": {}
},
{
"label": "backpack",
"points": [
[
108.88825214899715,
19.684813753581675
],
[
169.63323782234957,
132.2922636103152
]
],
"group_id": null,
"description": "",
"shape_type": "rectangle",
"flags": {}
},
{
"label": "suitcase",
"points": [
[
142.69914040114614,
125.41547277936962
],
[
254.77429459472592,
259.0
]
],
"group_id": null,
"description": "",
"shape_type": "rectangle",
"flags": {}
}
],
"imagePath": "aod (2).png",
"imageData": "xxxxxx...................................",
"imageHeight": 260,
"imageWidth": 396
}
.txt
为扩展名)包含了每个图像中对象的标注信息,格式通常如下:
:对象的类别索引(从0开始)。
、
:对象边界框中心相对于图像宽度和高度的坐标(范围通常在0到1之间)。
、
:对象边界框的宽度和高度相对于图像宽度和高度的比例(范围通常在0到1之间)。以下是一个示例:
0 0.5 0.4 0.2 0.3
1 0.3 0.6 0.4 0.5
在此示例中,有两个对象被标注。第一个对象属于类别0,其边界框中心位于图像宽度的50%和高度的40%,宽度占图像宽度的20%,高度占图像高度的30%。第二个对象属于类别1,其边界框中心位于图像宽度的30%和高度的60%,宽度占图像宽度的40%,高度占图像高度的50%。
import os
import numpy as np
import json
from glob import glob
import cv2
from sklearn.model_selection import train_test_split
from os import getcwd
def get_file(json_path,test):
files = glob(json_path + "*.json")
files = [i.replace("\\", "/").split("/")[-1].split(".json")[0] for i in files]
if test:
trainval_files, test_files = train_test_split(files, test_size=0.1, random_state=55)
else:
trainval_files = files
test_files = []
return trainval_files, test_files
def convert(size, box):
dw = 1. / (size[0])
dh = 1. / (size[1])
x = (box[0] + box[1]) / 2.0 - 1
y = (box[2] + box[3]) / 2.0 - 1
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)
#
# print(wd)
def json_to_txt(json_path,files, txt_name,classes):
if not os.path.exists('tmp/'):
os.makedirs('tmp/')
list_file = open('tmp/%s.txt' % (txt_name), 'w')
for json_file_ in files:
# print(json_file_)
json_filename = json_path + json_file_ + ".json"
imagePath = json_path + json_file_ + ".jpg"
list_file.write('%s/%s\n' % (wd, imagePath))
out_file = open('%s/%s.txt' % (json_path, json_file_), 'w')
json_file = json.load(open(json_filename, "r", encoding="utf-8"))
height, width, channels = cv2.imread(json_path + json_file_ + ".jpg").shape
for multi in json_file["shapes"]:
points = np.array(multi["points"])
xmin = min(points[:, 0]) if min(points[:, 0]) > 0 else 0
xmax = max(points[:, 0]) if max(points[:, 0]) > 0 else 0
ymin = min(points[:, 1]) if min(points[:, 1]) > 0 else 0
ymax = max(points[:, 1]) if max(points[:, 1]) > 0 else 0
label = multi["label"]
if xmax <= xmin:
pass
elif ymax <= ymin:
pass
else:
cls_id = classes.index(label)
print(json_file_)
b = (float(xmin), float(xmax), float(ymin), float(ymax))
bb = convert((width, height), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
# print(json_filename, xmin, ymin, xmax, ymax, cls_id)
if __name__ == '__main__':
wd = getcwd()
classes_name = ["person","sack", "elec", "bag", "box", "um", "caron", "boot","pail"]
path = "xxxx/images/"
train_file,test_file = get_file(path,False)
json_to_txt(path,train_file,"train",classes_name)
path = “xxxx/images/” 是标注好的数据所在的目标,里面包含了原始数据和标签json文件,当运行完上面的脚本之后,在当前目录下会多出与每个图像名称相同的txt文件。
在项目根目录下创建一个dataset的目录,并在dataset目录添加三个目录,分别是images,json,labels:
把数据集里面的所有图像都拷贝到dataset/images目录下,把json文件拷贝到dataset/json目录里面,把生成的txt标签文件拷贝到dataset/labels目录下。
转换完成之后,要验证数据转换是否正确:
import cv2
import os
def Xmin_Xmax_Ymin_Ymax(img_path, txt_path):
"""
:param img_path: 图片文件的路径
:param txt_path: 标签文件的路径
:return:
"""
img = cv2.imread(img_path)
# 获取图片的高宽
h,w, _ = img.shape
con_rect = []
# 读取TXT文件 中的中心坐标和框大小
with open(txt_path, "r") as fp:
# 以空格划分
lines =fp.readlines()
for l in lines:
contline= l.split(' ')
xmin = float((contline[1])) - float(contline[3]) / 2
xmax = float(contline[1]) + float(contline[3]) / 2
ymin = float(contline[2]) - float(contline[4]) / 2
ymax = float(contline[2].strip()) + float(contline[4].strip()) / 2
xmin, xmax = w * xmin, w * xmax
ymin, ymax = h * ymin, h * ymax
con_rect.append((contline[0], xmin, ymin, xmax, ymax))
return con_rect
#根据label坐标画出目标框
def plot_tangle(img_dir,txt_dir):
contents = os.listdir(img_dir)
for file in contents:
img_path = os.path.join(img_dir,file)
img = cv2.imread(img_path)
txt_path = os.path.join(txt_dir,(os.path.splitext(os.path.basename(file))[0] + ".txt"))
con_rect = Xmin_Xmax_Ymin_Ymax(img_path, txt_path)
for rect in con_rect:
cv2.rectangle(img, (int(rect[1]), int(rect[2])), (int(rect[3]), int(rect[4])), (0, 0, 255))
cv2.namedWindow()
cv2.imshow("src",img)
cv2.waitKey()
if __name__=="__main__":
img_dir = r"xxx\images"
txt_dir = r"xxx\labels"
plot_tangle(img_dir,txt_dir)
在深度学习中,数据集分割的目标仍然是将数据划分为训练集、验证集和测试集,但由于深度学习模型通常具有更多的参数和复杂性,因此划分时需要考虑更多的因素。以下是深度学习数据集分割的一般步骤:
训练集(Training Set):
验证集(Validation Set):
测试集(Test Set):
一般而言,数据集分割的比例可能是 70%-15%-15% 或 80%-10%-10%。在深度学习中通常会追求更大的数据集,因此可以有更多的数据用于训练。
数据集分割时需要注意以下几点:
样本均衡: 确保每个分组中的类别分布相似,以避免模型过度适应于某些特定类别。
随机性: 使用随机种子(例如,random_state
参数)以确保划分的重复性。
数据预处理一致性: 确保对数据的任何预处理步骤在所有分组上都是一致的,以防止引入不一致性。
在深度学习任务中,合适的数据集分割是构建有效模型的重要一环,可以帮助评估模型的性能、优化超参数,并准确衡量模型在未见过数据上的表现。
分割代码:
# -*- coding:utf-8 -*
import os
import random
import os
import shutil
def data_split(full_list, ratio):
n_total = len(full_list)
offset = int(n_total * ratio)
if n_total == 0 or offset < 1:
return [], full_list
random.shuffle(full_list)
sublist_1 = full_list[:offset]
sublist_2 = full_list[offset:]
return sublist_1, sublist_2
train_p="dataset/train"
val_p="dataset/val"
imgs_p="images"
labels_p="labels"
#创建训练集
if not os.path.exists(train_p):#指定要创建的目录
os.mkdir(train_p)
tp1=os.path.join(train_p,imgs_p)
tp2=os.path.join(train_p,labels_p)
print(tp1,tp2)
if not os.path.exists(tp1):#指定要创建的目录
os.mkdir(tp1)
if not os.path.exists(tp2): # 指定要创建的目录
os.mkdir(tp2)
#创建测试集文件夹
if not os.path.exists(val_p):#指定要创建的目录
os.mkdir(val_p)
vp1=os.path.join(val_p,imgs_p)
vp2=os.path.join(val_p,labels_p)
print(vp1,vp2)
if not os.path.exists(vp1):#指定要创建的目录
os.mkdir(vp1)
if not os.path.exists(vp2): # 指定要创建的目录
os.mkdir(vp2)
#数据集路径
images_dir="D:/DL/ultralytics/dataset/images"
labels_dir="D:/DL/ultralytics/dataset/labels"
#划分数据集,设置数据集数量占比
proportion_ = 0.9 #训练集占比
total_file = os.listdir(images_dir)
num = len(total_file) # 统计所有的标注文件
list_=[]
for i in range(0,num):
list_.append(i)
list1,list2=data_split(list_,proportion_)
for i in range(0,num):
file=total_file[i]
print(i,' - ',total_file[i])
name=file.split('.')[0]
if i in list1:
jpg_1 = os.path.join(images_dir, file)
jpg_2 = os.path.join(train_p, imgs_p, file)
txt_1 = os.path.join(labels_dir, name + '.txt')
txt_2 = os.path.join(train_p, labels_p, name + '.txt')
if os.path.exists(txt_1) and os.path.exists(jpg_1):
shutil.copyfile(jpg_1, jpg_2)
shutil.copyfile(txt_1, txt_2)
elif os.path.exists(txt_1):
print(txt_1)
else:
print(jpg_1)
elif i in list2:
jpg_1 = os.path.join(images_dir, file)
jpg_2 = os.path.join(val_p, imgs_p, file)
txt_1 = os.path.join(labels_dir, name + '.txt')
txt_2 = os.path.join(val_p, labels_p, name + '.txt')
shutil.copyfile(jpg_1, jpg_2)
shutil.copyfile(txt_1, txt_2)
print("数据集划分完成: 总数量:",num," 训练集数量:",len(list1)," 验证集数量:",len(list2))
在ultralytics/cfg/datasets目录下复制一份coco.yaml复制ultralytics根目录,重新命名成my_coco.yaml,然后把文件内容改成自己的数据路径和自己所标注的数据名称。
# Ultralytics YOLO , AGPL-3.0 license
# COCO8 dataset (first 8 images from COCO train2017) by Ultralytics
# Example usage: yolo train data=coco8.yaml
# parent
# ├── ultralytics
# └── datasets
# └── coco8 ← downloads here (1 MB)
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: D:/DL/ultralytics # dataset root dir
train: dataset/train # train images (relative to 'path') 4 images
val: dataset/val # val images (relative to 'path') 4 images
test: # test images (optional)
# Classes
names:
0: person
1: sack
2: elec
3: bag
4: box
5: um
6: caron
7: boot
8: pail
# Download script/URL (optional)
download: https://ultralytics.com/assets/coco8.zip
模型训练有两种方式,直接pip安装ultralytics库的和源码安装的训练方法有差异。
单卡
yolo detect train data=my_coco.yaml model=yolov8s.pt epochs=150 imgsz=640 batch=64 workers=0 device=0
多卡训练
yolo detect train data=my_coco.yaml model=./weights/yolov8s.pt epochs=150 imgsz=640 batch=128 workers= \'0,1,2,3\' device=0,1,2
在根目录下新建一个train.py的文件
from ultralytics import YOLO
#train
model = YOLO('my_coco.yaml').load('yolov8s.pt') # build from YAML and transfer weights
# Train the model
model.train(data='./ultralytics/datasets/my_coco.yaml', epochs=150, imgsz=640,batch=2, workers=0)
在yolo环境下运行下面指令,用来验证训练的结果:
yolo task=detect mode=predict model=last.pt source='1.jpg' show=True
关于模型推理部署,可以看我之前的博客:https://blog.csdn.net/matt45m/article/details/134221201?spm=1001.2014.3001.5502