labelme标注的json文件,转变成txt文件的代码
时间: 2025-07-25 12:27:37 AIGC 浏览: 43
<think>我们使用labelme标注的JSON文件通常包含图像中的对象(多边形、矩形、点等)的标注信息。每个JSON文件对应一张图像,包含图像路径、尺寸以及标注对象的列表。
要将labelme的JSON文件转换为YOLO格式的txt文件(用于目标检测),我们需要:
1. 读取JSON文件。
2. 获取图像的宽度和高度(用于归一化坐标)。
3. 遍历每个标注对象(shapes):
- 只处理矩形(rectangle)标注(因为YOLO目标检测使用矩形框)。
- 获取矩形框的两个点(左上和右下),并转换为中心点坐标和宽高(归一化到0-1)。
- 根据类别名称确定类别ID(需要预先定义类别列表)。
4. 将每个矩形框的信息写入txt文件(每行一个对象,格式:class_id center_x center_y width height)。
注意:如果标注中有其他形状(如多边形、点等),在目标检测任务中我们只关心矩形框。
但是,如果任务还包括关键点检测(如之前的问题),那么转换会更复杂。不过根据问题,这里只要求转换为txt文件(假设是目标检测的YOLO格式)。
以下代码实现将labelme的矩形标注转换为YOLO格式的txt文件。
步骤:
1. 定义类别列表(根据你的数据集,例如:["person", "car", ...])。
2. 遍历每个JSON文件。
3. 对每个JSON文件,生成一个同名的txt文件(放在同一目录或指定目录)。
代码示例:</think>以下是将 LabelMe JSON 标注文件转换为 YOLO 格式 TXT 文件的完整 Python 代码实现:
```python
import json
import os
from pathlib import Path
def labelme_to_yolo(json_path, output_dir, class_names):
"""
将 LabelMe JSON 文件转换为 YOLO 格式的 TXT 文件
参数:
json_path: LabelMe JSON 文件路径
output_dir: 输出 TXT 文件目录
class_names: 类别名称列表(按索引顺序)
"""
# 确保输出目录存在
Path(output_dir).mkdir(parents=True, exist_ok=True)
# 读取 JSON 文件
with open(json_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# 获取图像尺寸
img_width = data['imageWidth']
img_height = data['imageHeight']
# 准备输出文件路径
txt_filename = Path(json_path).stem + '.txt'
txt_path = os.path.join(output_dir, txt_filename)
# 处理每个标注对象
yolo_lines = []
for shape in data['shapes']:
# 只处理矩形标注
if shape['shape_type'] != 'rectangle':
continue
# 获取类别索引
label = shape['label']
try:
class_id = class_names.index(label)
except ValueError:
# 如果类别不在列表中,跳过或添加新类别
print(f"警告: 类别 '{label}' 未在 class_names 中定义")
continue
# 获取矩形坐标
points = shape['points']
x1, y1 = points[0]
x2, y2 = points[1]
# 确保坐标顺序正确
x_min = min(x1, x2)
x_max = max(x1, x2)
y_min = min(y1, y2)
y_max = max(y1, y2)
# 转换为 YOLO 格式 (归一化中心坐标和宽高)
x_center = (x_min + x_max) / 2 / img_width
y_center = (y_min + y_max) / 2 / img_height
width = (x_max - x_min) / img_width
height = (y_max - y_min) / img_height
# 格式化为 YOLO 行
yolo_line = f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}"
yolo_lines.append(yolo_line)
# 写入 TXT 文件
with open(txt_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(yolo_lines))
print(f"已转换: {json_path} -> {txt_path}")
# 示例用法
if __name__ == "__main__":
# 配置参数
json_dir = "path/to/labelme_jsons" # LabelMe JSON 文件目录
output_dir = "path/to/yolo_labels" # 输出 TXT 文件目录
class_names = ["person", "car", "dog", "cat"] # 你的类别列表
# 处理目录中的所有 JSON 文件
for json_file in Path(json_dir).glob('*.json'):
labelme_to_yolo(str(json_file), output_dir, class_names)
```
### 代码详细解释:
1. **函数定义**:
- `labelme_to_yolo()` 是核心转换函数
- 参数:
- `json_path`: LabelMe JSON 文件路径
- `output_dir`: 输出 TXT 文件目录
- `class_names`: 类别名称列表(顺序决定类别ID)
2. **关键处理步骤**:
- **读取 JSON 数据**:使用 `json.load()` 读取标注文件
- **获取图像尺寸**:从 JSON 中提取 `imageWidth` 和 `imageHeight`
- **处理矩形标注**:
- 只处理 `shape_type` 为 `rectangle` 的对象
- 根据 `label` 获取类别ID(在 `class_names` 中的索引)
- **坐标转换**:
- 确保坐标顺序正确(左上和右下点)
- 计算边界框中心点坐标(归一化到 0-1)
- 计算边界框宽度和高度(归一化到 0-1)
- **生成 YOLO 格式**:
- 每行格式:`class_id center_x center_y width height`
- 保留6位小数精度
3. **文件输出**:
- 输出文件名与 JSON 文件同名(扩展名改为 `.txt`)
- 每个对象一行,多对象用换行分隔
### 转换前后格式对比:
**LabelMe JSON 格式**:
```json
{
"version": "5.8.1",
"flags": {},
"shapes": [
{
"label": "person",
"points": [[564.28, 679.28], [1152.64, 1079.0]],
"shape_type": "rectangle"
},
{
"label": "car",
"points": [[200.0, 300.0], [400.0, 500.0]],
"shape_type": "rectangle"
}
],
"imageWidth": 1920,
"imageHeight": 1080
}
```
**YOLO TXT 格式**:
```
0 0.447135 0.813690 0.306542 0.370370
1 0.156250 0.370370 0.104167 0.185185
```
### 进阶功能扩展(支持多边形和关键点):
如果需要处理多边形或关键点标注,可以扩展函数:
```python
# 在 labelme_to_yolo 函数中添加以下处理逻辑
for shape in data['shapes']:
# 处理多边形标注
if shape['shape_type'] == 'polygon':
points = shape['points']
# 转换为边界框
x_coords = [p[0] for p in points]
y_coords = [p[1] for p in points]
x_min, x_max = min(x_coords), max(x_coords)
y_min, y_max = min(y_coords), max(y_coords)
# 后续转换与矩形相同...
# 处理关键点标注
elif shape['shape_type'] == 'point':
# 需要结合对象ID处理,通常需要额外逻辑关联到对象
pass
```
### 批量转换脚本:
```python
import glob
def batch_convert_labelme_to_yolo(json_dir, output_dir, class_names):
"""批量转换目录中的所有 LabelMe JSON 文件"""
json_files = glob.glob(os.path.join(json_dir, '*.json'))
total = len(json_files)
print(f"开始转换 {total} 个 JSON 文件...")
for i, json_file in enumerate(json_files):
labelme_to_yolo(json_file, output_dir, class_names)
print(f"进度: {i+1}/{total} - {os.path.basename(json_file)}")
print(f"转换完成! 文件保存在: {output_dir}")
# 使用示例
batch_convert_labelme_to_yolo(
json_dir="path/to/labelme_annotations",
output_dir="path/to/yolo_labels",
class_names=["person", "car", "dog"]
)
```
### 注意事项:
1. **类别名称**:确保 `class_names` 列表与你的数据集一致且顺序正确
2. **坐标顺序**:LabelMe 的矩形点顺序不固定,代码会自动处理
3. **图像尺寸**:YOLO 需要归一化坐标,因此需要正确的图像尺寸
4. **非矩形标注**:当前代码只处理矩形,如需多边形需扩展逻辑
5. **关键点**:关键点需要不同的处理逻辑,通常需要关联到特定对象
---
阅读全文
相关推荐


















