ExDark数据集标签转yolo格式(易懂)
一、前言
知道大家为何而来,因此作者不必废话直接上代码。代码已经详细注释,如果读者还有不懂的地方,在评论区留言,我将在48小时内回复你(如果我没毕业的话)。
二、代码
import os
import cv2
import re
# 定义类别列表
categSrces = ['Bicycle', 'Boat', 'Bottle', 'Bus', 'Car', 'Cat', 'Chair', 'Cup', 'Dog', 'Motorbike', 'People', 'Table']
# 函数:将类别名称转换为类别索引
def Get_Cls_Index(Cls_Name):
if Cls_Name in categSrces:
return categSrces.index(Cls_Name)
else:
raise ValueError(f"Class '{Cls_Name}' not found in the category list.")
# 函数:将标签文件内容转换为 YOLO 格式
def Convert_to_yolo_label(Img_Folder, Src, Dst):
# 检查源文件夹是否存在
if not os.path.exists(Src):
raise ValueError("Src does not exist.")
# 检查目标文件夹是否存在,如果不存在,则创建它
if not os.path.exists(Dst):
os.makedirs(Dst)
for file in os.listdir(Src):
with open(os.path.join(Src, file), 'r') as LabelFile:
# 正则表达式匹配
match = re.findall('([0-9]+_[0-9]+)(.[a-zA-z]+)(.[a-zA-Z]+)', file)[0]
Prefix = match[0] # 真实文件名(不带扩展名)
Img_Format = match[1] # 图像格式
lines = LabelFile.readlines() # 读取源标签文件内容
Yolo_File_Content = [] # 存储转换后的标签文件内容(每一个列表元素是一个目标的标签)
Save_File_Name = os.path.join(Dst, Prefix + '.txt') # 存储转换后的标签文件路径
# 读取对应的图片,并获取形状参数(高和宽)
img = cv2.imread(os.path.join(Img_Folder, Prefix+Img_Format))
img_height, img_width, _ = img.shape # 获取图像的高度和宽度
for line in lines[1:]: # 跳过文件版本行
# 解析标签文件内容,将标签信息读取出来
Labelinfo = line.strip().split()
# 解析标签文件内容,将标签信息读取出来
Cls_Name = Labelinfo[0]
x_min = float(Labelinfo[1])
y_min = float(Labelinfo[2])
box_width = float(Labelinfo[3])
box_height = float(Labelinfo[4])
# 计算Yolo标签格式:类别索引 标签框的中心点x坐标 标签框的中心点y坐标 宽度 高度
# 最后每一个参数计算参数都要归一化,后面除以高或宽就是为了归一化处理
Cls_Index = Get_Cls_Index(Cls_Name)
x_center = (x_min + box_width / 2) / img_width
y_center = (y_min + box_height / 2) / img_height
norm_width = box_width / img_width
norm_height = box_height / img_height
# 构建 YOLO 格式的标签行,并保存
yolo_label = f"{Cls_Index} {x_center:.6f} {y_center:.6f} {norm_width:.6f} {norm_height:.6f}\n"
Yolo_File_Content.append(yolo_label)
# 将转换后的标签文件内容写入目标文件
with open(Save_File_Name, 'w') as TargetFile:
TargetFile.writelines(Yolo_File_Content)
# 定义图像文件夹路径、源标签文件目录路径和目标标签文件目录路径
Img_Folder = r'E:\Datasets\ExDark\images'
Src = r'E:\Datasets\ExDark\Annotations'
Dst = r'E:\Datasets\ExDark\Annotations_yolo'
# 调用函数,将ExDark的标签文件转换为 YOLOv 格式
Convert_to_yolo_label(Img_Folder, Src, Dst)
三、注意事项
- 代码拷贝后记得修改路径
- 文章对于源标签文件名的各部分(真实文件名、图像格式和文本文件后缀)提取使用了正则表达式。
- 正则表达式是非常强大的东西,本着
授人以鱼不如授人以渔
的初心和目的,希望大家能理解上述正则表达式,这里我提供了大家网页学习的路径- 正则表达式 – 语法 | 菜鸟教程 (runoob.com)
- 如果嫌麻烦,那么下面是简单的对正则表达式语法的介绍(已足够读者理解代码中的正则表达式)
- 匹配字符
.
:匹配任意字符(除了换行符)\w
:匹配任意字母数字字符(相当于[a-zA-Z0-9_]
)\W
:匹配任意非字母数字字符\d
:匹配任意数字字符(相当于[0-9]
)\D
:匹配任意非数字字符\s
:匹配任意空白字符(相当于[ \t\n\r\f\v]
)\S
:匹配任意非空白字符
- 边界匹配
^
:匹配字符串的开头$
:匹配字符串的结尾\b
:匹配一个单词边界\B
:匹配非单词边界
- 字符集
[abc]
:匹配方括号内的任意一个字符(此处为a
、b
或c
)[^abc]
:匹配不在方括号内的任意一个字符[a-z]
:匹配小写字母范围内的任意一个字符[A-Z]
:匹配大写字母范围内的任意一个字符[0-9]
:匹配数字范围内的任意一个字符
- 量词
*
:匹配前一个字符零次或多次+
:匹配前一个字符一次或多次?
:匹配前一个字符零次或一次{n}
:匹配前一个字符恰好n
次{n,}
:匹配前一个字符至少n
次{n,m}
:匹配前一个字符至少n
次,但不超过m
次
- 分组和引用
()
:匹配括号内的表达式,并记住匹配的文本|
:匹配|
左右任意一个表达式\num
:匹配num
所表示的分组(?P<name>...)
:匹配...
并将匹配结果命名为name
(?P=name)
:引用命名为name
的分组匹配结果
- 特殊序列
\A
:匹配字符串的开头\Z
:匹配字符串的结尾\
:将后面的字符转义为原始字符\g<name>
:引用命名为name
的分组匹配结果\number
:引用编号为number
的分组匹配结果
- 匹配字符