菜品目标检测数据集标注及处理Yolo
本文摘要
本文主要演示如何使用LabelImg标注菜品数据集,目前数据集有2000+已标注的菜品目标图片,用于后续的菜品目标深度学习模型训练(包含已标注数据集,点击原文链接,关注回复“源码或数据集”,免费获取)
1. 数据格式
目标检测的数据,在一张图像中,需要以最小外接矩形标记出各个目标区域的位置和类别,
一般的目标区域位置用一个矩形框来表示,一般用以下3种方式表达:
常见的目标检测数据集:
- VOC采用的[x1,y1,x2,y2],表示物体的最小外接矩形框,VOC数据指的是Pascal VOC比赛使用的数据。VOC数据是每个图像文件对应一个同名的xml文件,xml文件中标记物体框的坐标和类别等信息。
- COCO采用的[x1,y1,w,h],表示物体的最小外接矩形框,COCO数据是COCO比赛使用的数据。以json文件记录数据格式。
LabelImg可以标注VOC格式的数据,对图像做目标框的标注。
2. LabelImg标注工具下载
- 目标检测的数据标注,可以用LabelImg,下载地址:https://github.com/HumanSignal/labelImg/releases
- 建议直接下载其可执行程序,而不是通过pip安装使用。
- 是一款开源的图像标注工具,专门用于辅助计算机视觉任务的标注工作。它由python编写,并采用pyqt5作为图形用户界面的框架, LabelImg 是跨平台的,它可以在Windows、Linux 和 macOS 上运行,适应性强。
3. 数据集准备与标注
目前对于菜品目标检测的已标注数据有2000+
打开labelImg,并打开images文件夹和xml文件夹,如下图所示:
点击画框create\nRectBox,调出十字光标,框”最小外接矩形框“,并输入标签,然后点击save,就保存了.xml标注文件
xml文件格式如下所示:
4. 将LabelImg标注的数据集转为Yolo训练格式
知道规则后,我们使用如下脚本进行批量转换即可,核心代码如下所示:
import os
from lxml import etree
import shutil
def delete_folder(folder_path):
try:
shutil.rmtree(folder_path)
print(f'文件夹: {folder_path} 所有内容已删除!')
except Exception as e:
print(f'删除文件夹及其所有内容报错: {e}')
def xml_to_yolotxt(source_path, label_path, cls=''):
if not os.path.exists(label_path):
os.mkdir(label_path)
# 获取xml文件名称列表
files = os.listdir(source_path)
classes = get_classes(files, source_path)
print('---获取所有xml文件中的cls=', classes)
# classes = ['fire']
# 生成分类字典,列如{'apple':0,'banana':1}
class_dict = dict(zip(classes,range(len(classes))))
print('------生成分类字典=', class_dict)
# class_dict = {'fire': 1}
# class_dict = {cls: 0}
print('---------------begin convert----')
count = 0
if 1:
for file in files:
count = count + 1
# print('------------', file)
convert_xml2txt(file, source_path, label_path, class_dict, norm=True)
print('---------------finish convert----,count=', count)
def convert_xml2txt(file_name, source_path, label_path, class_dict, norm=False):
# 创建txt文件,并打开、写入
new_name = file_name.split('.')[0] + '.txt'
f = open(label_path+'/'+new_name,'w')
print('-----------------------name=', new_name)
with open(source_path+file_name,'rb') as fb:
# 开始解析xml文件,获取图像尺寸
xml = etree.HTML(fb.read())
width = int(xml.xpath('//size/width/text()')[0])
height = int(xml.xpath('//size/height/text()')[0])
# 获取对象标签
labels = xml.xpath('//object') # 单张图片中的目标数量 len(labels)
for label in labels:
name = label.xpath('./name/text()')[0]
label_class = class_dict[name]
xmin = int(label.xpath('./bndbox/xmin/text()')[0])
xmax = int(label.xpath('./bndbox/xmax/text()')[0])
ymin = int(label.xpath('./bndbox/ymin/text()')[0])
ymax = int(label.xpath('./bndbox/ymax/text()')[0])
# xyxy-->xywh,且归一化
if norm :
dw = 1 / width
dh = 1 / height
x_center = (xmin + xmax) / 2
y_center = (ymax + ymin) / 2
w = (xmax - xmin)
h = (ymax - ymin)
x, y, w, h = x_center * dw, y_center * dh, w * dw, h * dh
f.write(str(label_class)+' '+str(x)+' '+str(y)+' '+str(w)+' '+str(h)+' '+'\n')
#关闭文件
f.close()
# 获取分类名称列表
def get_classes(files, source_path):
class_set = set([])
for file in files:
with open(source_path+file,'rb') as fb:
#解析xml文件
xml = etree.HTML(fb.read())
labels = xml.xpath('//object')
for label in labels:
name = label.xpath('./name/text()')[0]
class_set.add(name)
return list(class_set)
if __name__ == '__main__':
source_path = 'C:/mysel/food_plate_images/annotations_xmls/'
label_path = 'C:/mysel/food_plate_images/labels/'
delete_folder(label_path)
xml_to_yolotxt(source_path, label_path)
5. 将数据分成训练集、验证集、测试集
5.1 Yolo
5.1.1 yolo训练目录文件结构
5.1.2 使用脚本分数据集
使用脚本将所有数据按照80%、10%、10%分成训练集、验证集、测试集
import os
import shutil
import random
from math import ceil
# 定义源文件夹路径和目标文件夹路径
source_path_images = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/food_plate_images/images/'
source_path_labels = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/food_plate_images/labels/'
# 80% 的文件
train_folder_images = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/yolo_images/train/images'
train_folder_labels = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/yolo_images/train/labels'
# 10% 的文件
val_folder_images = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/yolo_images/val/images'
val_folder_labels = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/yolo_images/val/labels'
# 10% 的文件
test_folder_images = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/yolo_images/test/images'
test_folder_labels = 'C:/ai_datasets/菜品目标检测数据集(餐盘标注2000+)/yolo_images/test/labels'
def delete_folder(folder_path):
try:
shutil.rmtree(folder_path)
print(f'文件夹: {folder_path} 所有内容已删除!')
except Exception as e:
print(f'删除文件夹及其所有内容报错: {e}')
delete_folder(train_folder_images)
delete_folder(train_folder_labels)
delete_folder(val_folder_images)
delete_folder(val_folder_labels)
delete_folder(test_folder_images)
delete_folder(test_folder_labels)
# 确保目标文件夹存在,不存在则创建
os.makedirs(train_folder_images, exist_ok=True)
os.makedirs(train_folder_labels, exist_ok=True)
os.makedirs(val_folder_images, exist_ok=True)
os.makedirs(val_folder_labels, exist_ok=True)
os.makedirs(test_folder_images, exist_ok=True)
os.makedirs(test_folder_labels, exist_ok=True)
# 获取所有 .jpg 文件
jpg_files = [f for f in os.listdir(source_path_images) if f.endswith('.jpg')]
# 随机打乱文件顺序
random.shuffle(jpg_files)
# 计算每个文件夹的分配数量
total_files = len(jpg_files)
train_count = ceil(total_files * 0.8)
val_count = ceil(total_files * 0.1)
test_count = total_files - train_count - val_count
# 分配文件
train_files = jpg_files[:train_count]
val_files = jpg_files[train_count:train_count + val_count]
test_files = jpg_files[train_count + val_count:]
# 复制文件到对应文件夹
def copy_files(file_list, source_image_folder, destination_image_folder, source_txt_folder, dest_txt_folder):
for file_name in file_list:
print(f'处理---- file=', file_name)
# 处理 .jpg 文件
jpg_source_file = os.path.join(source_image_folder, file_name)
jpg_destination_file = os.path.join(destination_image_folder, file_name)
shutil.copy(jpg_source_file, jpg_destination_file)
# 处理对应的 .txt 文件
txt_file_name = file_name.replace('.jpg', '.txt')
txt_source_file = os.path.join(source_txt_folder, txt_file_name)
if os.path.exists(txt_source_file): # 如果存在对应的 .txt 文件
txt_destination_file = os.path.join(dest_txt_folder, txt_file_name)
shutil.copy(txt_source_file, txt_destination_file)
# 执行复制
copy_files(train_files, source_path_images, train_folder_images, source_path_labels, train_folder_labels)
copy_files(val_files, source_path_images, val_folder_images, source_path_labels, val_folder_labels)
copy_files(test_files, source_path_images, test_folder_images, source_path_labels, test_folder_labels)
5.1.3 Yolo data.yaml
train: C:/xxx/菜品目标检测数据集2600+/images/train
val: C:/xxx/菜品目标检测数据集2600+/images/val
test: C:/xxx/菜品目标检测数据集2600+/images/test
nc: 1
names: ["label"]
往期文章回顾
结束语
文中源码及数据集文件【获取方式】:点击原文根据提示获取!!!
原文地址:https://blog.csdn.net/oBoLuoChuiXue12/article/details/142890244
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!