1 Python库准备
1.1 安装pyqt
conda install pyqt
1.2 安装pillow
conda install pillow
1.3 安装labelme
Labelme是一个用于图像标注的开源工具,可以实现图像标注、语义分割、实例分割等
- pip install labelme
刚刚安装的东西就在这个目录下面,我的是D:\anaconda3\envs\cv_env\Scripts
2 使用labelimg
2.1 打开labelimg
2.1.1 第一种启动方式
2.1.2 第二种启动方式
- 打开Annconda的安装目录D:\anaconda3\envs(这里是我的安装路径)
- 在envs里面就是所有创建的虚拟环境,进入刚刚使用的虚拟环境
- 在 D:\Anaconda3\envs\test\Scripts目录下,在上方输入
cmd
进入到虚拟环境中- 双击打开labelme
2.2 批注图像
在labelme软件中,最主要的几个功能如下:
- 打开:只打开一张图像进行标注,通过打开目录打开包含图像的文件夹,进行标注比较方便
- 打开目录:点击后会弹出一个窗口,选择一个文件夹,文件夹中包含要进行标注的图像
- 下一幅:在打开目录的情况下,点击后可切换到上一张图片
- 上一幅:在打开目录的情况下,点击后可切换到下一张图片
- 保存:在标注完成后,会生成标签文件,保存选项即选择本地的一个文件夹保存标签文件。
- 创建多边形:这一个功能是最重要的,选择了一张图像后便可以进行标注,选择这个功能后即可这对界面中显示的图像进行分割标注,注意标注点要尽可能贴合目标
注意:在标注的时候,最后一个点要首尾相连。完成后会弹出一个窗口,在窗口内输入标签,确认后一幅图像就标注完成啦。这样便会在保存目录中生成标签的json文件
5 数据集制作
5.1 制作yolo格式的数据集
通过上面的手动批注得到的json数据的格式大致如此:
{
"version": "5.5.0",
"flags": {},
"shapes": [
{
"label": "edge",#标签(类别)
"points": [
[
x,//x 坐标
y //y 坐标
],
"group_id": null,
"description": "",
"shape_type": "polygon",
"flags": {},
"mask": null
},
],
"imagePath": "..\\images\\001.png",#图像路径
"imageData": "很长一段英文字母",
"imageHeight": 207,#图像高度
"imageWidth": 298#图像宽度
}
有shapes,labels,points等,还有图像的路径、高度和宽度
代码如下:
import json
import os
from tqdm import tqdm
def convert_label(json_dir, save_dir, classes):
"""
将COCO格式的JSON标注文件转换为YOLO格式的TXT文件。
参数:
json_dir (str): JSON标注文件的目录路径
save_dir (str): 转换后的TXT文件的目录路径
classes (str): 类别名称
"""
# 获取所有json文件名
json_paths = os.listdir(json_dir)
# 将类别字符串分割成列表
classes_list = classes.split(',')
# 遍历每个json文件
for json_path in tqdm(json_paths, desc="Processing JSON files"):
# 构建json文件的完整路径
path = os.path.join(json_dir, json_path)
# 打开并读取json文件内容
with open(path, 'r', encoding='utf-8') as load_f:
json_dict = json.load(load_f)
# 获取图片的高度和宽度
h, w = json_dict['imageHeight'], json_dict['imageWidth']
# 构建保存txt文件的路径,并打开文件准备写入
txt_path = os.path.join(save_dir, json_path.replace('.json', '.txt'))
with open(txt_path, 'w', encoding='utf-8') as txt_file:
# 遍历每个形状(shape)对象
for shape_dict in json_dict['shapes']:
# 获取当前形状的标签,并确定其在类别列表中的索引
label = shape_dict['label']
try:
label_index = classes_list.index(label)
except ValueError:
print(f"警告:未找到类别 '{label}',跳过此标注。")
continue
# 获取当前形状的所有点坐标
points = shape_dict['points']
# 归一化点坐标,并转换为字符串列表
points_nor_list = []
for point in points:
points_nor_list.append(str(point[0] / w))
points_nor_list.append(str(point[1] / h))
# 将归一化的点坐标连接成一个字符串
points_nor_str = ' '.join(points_nor_list)
# 创建YOLO格式的标签行
label_str = f"{label_index} {points_nor_str}\n"
# 写入到txt文件中
txt_file.write(label_str)
if __name__ == "__main__":
# 定义JSON文件所在的目录路径
json_dir = 'E:\\code\\python_pycharm\\Test\\数字图像\\作业\\第三次\\json'
# 定义保存转换后TXT文件的目录路径
save_dir = 'E:\\code\\python_pycharm\\Test\\数字图像\\作业\\第三次\\txt'
# 定义类别名称,用逗号分隔
classes = 'edge,lung,nodule'
# 调用函数进行转换
convert_label(json_dir, save_dir, classes)
转换后的txt数据的格式:
- txt数据的结构只是简单的用数字标注了类别,后面紧跟数据点的坐标,这样的数据在训练时候不需要再进行处理,比json格式的更好
4 报错问题
1
OSError: cannot write mode RGBA as JPEG
随便把png格式的图片的后缀名改为jpg造成的
- 查资料发现是PNG有RGBA四个通道,而JPG是RGB三个通道,所以PNG转BMP时候程序不知道A通道怎么办,就会产生错误