少女祈祷中...

发现新版本

网站好像有新内容,是否更新(゚⊿゚)ツ?

项目地址:yolov8镜像一键部署运行与云服务器

数据标注工具

针对与yolo系列模型,拉姆推荐使用LabelImg,而框框可以旋转的roLabelImg或者多边形标记的labelme拉姆都不推荐,因为到最后的yolo格式需要自己转换,并且效果不好

仅针对于拉姆自己数据集的测试

YOLO格式:类别ID和边界框坐标(中心x, 中心y, 宽度, 高度)

对于标签类别ID,有的时候会很乱,比如,person的ID应该为83,但实际上,在使用LabelImg标签标记的时候是0,所以,可以用下面的脚本来创建一个字典映射进行更改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# -*- coding: utf-8 -*-
import os

# 定义字符映射字典
char_mapping = {'0': '83',
'1': '84'}

# 定义输入和输出文件夹路径
input_folder = r'F:\work\1' # 请改成自己的输入路径
output_folder = r'F:\work\2' # 请改成自己的输出路径

# 确保输出文件夹存在
if not os.path.exists(output_folder):
os.makedirs(output_folder)

# 遍历输入文件夹中的所有.txt文件
for filename in os.listdir(input_folder):
if filename.endswith('.txt'):
input_file_path = os.path.join(input_folder, filename)
output_file_path = os.path.join(output_folder, filename)

# 读取文件内容
with open(input_file_path, 'r', encoding='utf-8') as file:
lines = file.readlines()

# 处理每一行从第一个字符到第一个空格结束的部分
modified_lines = []
for line in lines:
# 查找第一个空格的位置
space_index = line.find(' ')
if space_index != -1:
# 获取从第一个字符到第一个空格的部分
first_part = line[:space_index]
# 进行映射替换
modified_first_part = char_mapping.get(first_part, first_part)
# 替换并添加到修改后的行列表中
modified_line = modified_first_part + line[space_index:]
else:
# 如果没有空格,直接进行映射替换
modified_line = char_mapping.get(line.strip(), line.strip())
modified_lines.append(modified_line)

# 将修改后的内容写入输出文件
with open(output_file_path, 'w', encoding='utf-8') as file:
file.writelines(modified_lines)

print("处理完成,结果已保存到", output_folder)

注意更改为自己的路径哦~

当然你如果想用多边形标记工具labelme(这个只能保存为json格式)

拉姆也有两个脚本,可以进行转正为yolo模型可以识别的相对路径txt格式:

脚本一:将json转换成txt格式,因为labelme标签ID为自己输入的字母或者其他字符而不是类别ID,所以还需要脚本二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# -*- coding: utf-8 -*-
import json
import os
import cv2

img_folder_path = r'F:\work\1\images' # 图片存放文件夹
folder_path = r"F:\work\1\label" # 标注数据的文件地址
txt_folder_path = r"F:\work\1\txt" # 转换后的txt标签文件存放的文件夹


# 保存为相对坐标形式 :label x_center y_center w h
def relative_coordinate_txt(img_name, json_d, img_path):
src_img = cv2.imread(img_path)
if src_img is None:
print(f"Failed to read image: {img_path}")
return
h, w = src_img.shape[:2]
txt_name = img_name.split(".")[0] + ".txt"
txt_path = os.path.join(txt_folder_path, txt_name)
print(txt_path)
with open(txt_path, 'w') as f:
for item in json_d["shapes"]:
point = item['points']
# 确保 point[0] 和 point[1] 的坐标值正确
x1, y1 = point[0]
x2, y2 = point[1]
x_min = min(x1, x2)
x_max = max(x1, x2)
y_min = min(y1, y2)
y_max = max(y1, y2)

x_center = (x_min + x_max) / 2
y_center = (y_min + y_max) / 2
width = x_max - x_min
height = y_max - y_min

f.write("{} ".format(item['label']))
f.write("{} ".format(x_center / w))
f.write("{} ".format(y_center / h))
f.write("{} ".format(width / w))
f.write("{} ".format(height / h))
f.write("\n")

i = 0
for jsonfile in os.listdir(folder_path):
temp_path = os.path.join(folder_path, jsonfile)

i += 1
# if i > 5:
# break
# 如果是一个子目录就继续
if os.path.isdir(temp_path):
continue
print("json_path:\t", temp_path)
jsonfile_path = temp_path
with open(jsonfile_path, "r", encoding='utf-8') as f:
json_d = json.load(f)
# 保留原始扩展名,而不是强制转换为.jpeg,支持各类图片的格式
img_name = json_d['imagePath'].split("\\")[-1]
img_path = os.path.join(img_folder_path, img_name)
print("img_path:\t", img_path)
relative_coordinate_txt(img_name, json_d, img_path)

脚本二:处理labelme标签ID,将其转换为类别ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# -*- coding: utf-8 -*-
import os
import shutil

def process_label_files(input_dir, output_dir):
"""
处理标签文件,将特定标签名称转换为数字编号
Args:
input_dir: 输入文件夹路径
output_dir: 输出文件夹路径
"""
# 创建标签映射字典
label_mapping = {
'person': '4',
'ECGmonitor': '2',
'patientBed': '1',
'bedsideTable': '0',
'patient': '3'
# 可以根据需要添加更多映射
}
# 确保输出目录存在
if not os.path.exists(output_dir):
os.makedirs(output_dir)

# 遍历输入目录中的所有txt文件
for filename in os.listdir(input_dir):
if filename.endswith('.txt'):
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(output_dir, filename)

# 读取并处理文件
with open(input_path, 'r', encoding='utf-8') as f:
lines = f.readlines()

# 处理每一行
processed_lines = []
for line in lines:
parts = line.strip().split()
if parts: # 确保行不为空
# 替换标签
if parts[0] in label_mapping:
parts[0] = label_mapping[parts[0]]
processed_line = ' '.join(parts)
processed_lines.append(processed_line + '\n')

# 写入新文件
with open(output_path, 'w', encoding='utf-8') as f:
f.writelines(processed_lines)


# 路径更改
input_directory = r'F:\work\1' # 改为自己的输入路径
output_directory = r'F:\work\2' # 改为自己的输出路径

try:
process_label_files(input_directory, output_directory)
print(f"处理完成!文件已保存到: {output_directory}")
except Exception as e:
print(f"处理过程中出现错误: {str(e)}")

训练模型

  1. 首先在终端进入目录:ultralytics-8.3.27,在终端输入命令:
1
cd ultralytics-8.3.27
  1. 在ultralytics-8.3.27里找到train_v8.py文件,更改其代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import sys
import argparse
import os
from ultralytics import YOLO
import yaml

def main(opt):
yaml_path = opt.cfg
weights = opt.weights
config_path = opt.config

# 加载配置文件
with open(config_path, 'r') as f:
config = yaml.safe_load(f)

model = YOLO(yaml_path).load(weights)
model.info()

results = model.train(**config) # 使用配置文件中的所有参数

def parse_opt(known=False):
parser = argparse.ArgumentParser()
parser.add_argument('--cfg', type=str, default='ultralytics/cfg/models/v8/yolov8.yaml', help='model.yaml path')
parser.add_argument('--weights', type=str, default='', help='weights path')
parser.add_argument('--config', type=str, default='config.yaml', help='training config file')

opt = parser.parse_known_args()[0] if known else parser.parse_args()
return opt

if __name__ == "__main__":
opt = parse_opt()
main(opt)
  1. 在ultralytics-8.3.27上传配置文件coco128.yaml(可以根据自己的需求进行更改)
1
2
3
4
5
6
7
8
9
10
11
# 数据集位置
path: ../datasets/coco128 # dataset root dir
train: images/train2017 # train images (relative to 'path') 128 images
val: images/train2017 # val images (relative to 'path') 128 images
test: # test images (optional)

# 标签数量
nc: 86
# 标签名字
names: ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'patientBed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush', 'patient', 'bedsideTable', 'ECGmonitor', 'curtain', 'barcode','QRcode']

  1. 在ultralytics-8.3.27上传配置文件config.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 任务类型:目标检测
task: detect
# 运行模式:训练
mode: train
# 预训练模型:YOLOv8 Nano版本
model: yolov8n.pt
# 数据集配置文件:COCO128数据集
data: coco128.yaml
# 训练轮数:300轮
epochs: 300
# 输入图像尺寸:640x640像素
imgsz: 640
# 数据加载线程数:8个
workers: 8
# 批次样本数量:8个
batch: 8
# 初始学习率:0.0005
lr0: 0.0005
# 最终学习率:0.0005
lrf: 0.0005
# 动量参数:0.937
momentum: 0.937
# 权重衰减系数:0.0005
weight_decay: 0.0005
# 学习率预热轮数:3轮
warmup_epochs: 3.0
# 预热阶段动量参数:0.8
warmup_momentum: 0.8
# 预热阶段偏置项学习率:0.0001
warmup_bias_lr: 0.0001
  1. 记得更改ultralytics-8.3.27/ultralytics/cfg/models/v8/目录下的yolov8.yaml,将nc:80改成nc: 86(也就是你自己的标签数量)

  2. 最后进行模型的训练,在终端命令输入训练命令:

1
python train_v8.py --cfg ultralytics/cfg/models/v8/yolov8.yaml --weights yolov8n.pt --config config.yaml

模型预测

  1. 在ultralytics-8.3.27里找到predict.py文件,我们需要把进行一点路径更改:
1
2
model = YOLO('runs/detect/train/weights/best.pt')  # 训练好的模型位置
model.predict('datasets/coco128/images/train2017/', save=True, imgsz=640, conf=0.5) # 你的预测数据的位置
  1. predict.py里上面的路径也需要更改一下:
1
sys.path.append('/root/ultralytics-8.3.27/') # Path 以Autodl为例
  1. 在终端输入命令开始预测
1
python predict.py

收梢

在云服务器上进行训练还是很ok的,又便宜又快,比本地部署好用多了,就是需要一点略微花费。

数据标注真费事

阿门,下次有机会拉姆写写OCR或者MiniCPM-V-2.6

本文作者:戴诺斯·拉姆 @ 拉姆的小树屋

本文链接:https://sherry14love.github.io/2024/11/09/learn/yolov8/

本文版权:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

留言