在目标检测数据集处理中,我们经常会遇到标签之间不同格式的转化,以下介绍YOLO格式的标签转JSON格式。
通过labelimg标注的标签保存为如下txt文件:
txt格式YOLO标签
0 0.4296875 0.21597222222222223 0.1609375 0.43194444444444446
0 0.58203125 0.3138888888888889 0.1390625 0.5666666666666667
0 0.08554687500000001 0.19791666666666669 0.15703125 0.37083333333333335
0 0.90234375 0.23402777777777778 0.17500000000000002 0.4152777777777778
转化后的同labelme标注保存的json文件:
import os
import json
import base64
import cv2
def read_txt_file(txt_file):
with open(txt_file, 'r') as f:
lines = f.readlines()
data = []
for line in lines:
line = line.strip().split()
class_name = line[0]
bbox = [coord for coord in line[1:]]
data.append({'class_name': class_name, 'bbox': bbox})
return data
def convert_to_labelme(data, image_path, image_size):
labelme_data = {
'version': '4.5.6',
'flags': {},
'shapes': [],
'imagePath': json_image_path,
'imageData': None,
'imageHeight': image_size[0],
'imageWidth': image_size[1]
}
for obj in data:
dx = obj['bbox'][0]
dy = obj['bbox'][1]
dw = obj['bbox'][2]
dh = obj['bbox'][3]
w = eval(dw) * image_size[1]
h = eval(dh) * image_size[0]
center_x = eval(dx) * image_size[1]
center_y = eval(dy) * image_size[0]
x1 = center_x - w/2
y1 = center_y - h/2
x2 = center_x + w/2
y2 = center_y + h/2
if obj['class_name'] == '0': #判断对应的标签名称,写入json文件中
label = str('grape')
else:
label = obj['class_name']
shape_data = {
'label': label,
'points': [[x1, y1], [x2, y2]],
'group_id': None,
'shape_type': 'rectangle',
'flags': {}
}
labelme_data['shapes'].append(shape_data)
return labelme_data
def save_labelme_json(labelme_data, image_path, output_file):
with open(image_path, 'rb') as f:
image_data = f.read()
labelme_data['imageData'] = base64.b64encode(image_data).decode('utf-8')
with open(output_file, 'w') as f:
json.dump(labelme_data, f, indent=4)
# 设置文件夹路径和输出文件夹路径
txt_folder = r"E:\lwf_files\wanfu\01-yolo\yoloair\grape_dataset\labels\train" # 存放LabelImg标注的txt文件的文件夹路径
output_folder = r"E:\lwf_files\wanfu\01-yolo\yoloair\grape_dataset\labels\train" # 输出LabelMe标注的json文件的文件夹路径
img_folder = r"E:\lwf_files\wanfu\01-yolo\yoloair\grape_dataset\images\train" #存放对应标签的图片文件夹路径
# 创建输出文件夹
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 遍历txt文件夹中的所有文件
for filename in os.listdir(txt_folder):
if filename.endswith('.txt'):
# 生成对应的输出文件名
output_filename = os.path.splitext(filename)[0] + '.json'
# 读取txt文件
txt_file = os.path.join(txt_folder, filename)
data = read_txt_file(txt_file)
# 设置图片路径和尺寸
image_filename = os.path.splitext(filename)[0] + '.png' # 图片文件名与txt文件名相同,后缀为.jpg
image_path = os.path.join(img_folder, image_filename)
# image_size = (1280, 720) # 根据实际情况修改
json_image_path = image_path.split('\\')[-1]
image_size = cv2.imread(image_path).shape
# 转化为LabelMe格式
labelme_data = convert_to_labelme(data, image_path, image_size)
# 保存为LabelMe JSON文件
output_file = os.path.join(output_folder, output_filename)
save_labelme_json(labelme_data, image_path, output_file)
import cv2
import numpy as np
# 定义可视化函数
def visualize(image_path, label_path, class_names):
# 读取图片
image = cv2.imread(image_path)
# 获取图片的大小
height, width, _ = image.shape
# 读取标签文件
with open(label_path, "r") as f:
lines = f.readlines()
# 遍历每个标签
for line in lines:
# 解析标签
class_id, x, y, w, h = map(float, line.split())
class_name = class_names[int(class_id)]
# 计算 bounding box 的坐标
left = int((x - w / 2) * width)
top = int((y - h / 2) * height)
right = int((x + w / 2) * width)
bottom = int((y + h / 2) * height)
# 绘制 bounding box
cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2)
# 绘制类别名称
text_size, _ = cv2.getTextSize(class_name, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)
cv2.putText(image, class_name, (left, top - text_size[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# 显示图片
cv2.imshow("visualization", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 调用函数,可视化 YOLO 标签(请替换为你的图片路径、标签路径和类别名称列表)
visualize(r"F:\文件B_数集文件\B_葡萄数据\07-230612葡萄\0620_2_1.png", r"F:\文件B_数集文件\B_葡萄数据\07-230612葡萄\0620_2_1.txt", ["类别1", "类别2", "类别3"])