如何将图像标注的多边形坐标转换为YOLO格式矩形标注
任意点多边形标注转YOLO格式实现(水表ROI检测场景)
问题背景
- 做水表OCR读数识别时,首要步骤是提取表盘ROI区域
- 所用数据集的标注不是标准矩形框,而是任意顶点数的多边形结构:根据图像内容不同,多边形可能包含4、5、8个不等的坐标点
- 转换核心思路是取多边形的最小外接矩形,匹配YOLO检测格式要求,但原始标注为字符串存储的字典结构,解析环节存在障碍
原始标注格式
标注字段结构为文件名 | 水表读数值 | 多边形坐标,样例如下:
id_53_value_595_825.jpg 595.825 {'type': 'polygon', 'data': [{'x': 0.30788, 'y': 0.30207}, {'x': 0.30676, 'y': 0.32731}, {'x': 0.53501, 'y': 0.33068}, {'x': 0.53445, 'y': 0.33699}, {'x': 0.56529, 'y': 0.33741}, {'x': 0.56697, 'y': 0.29786}, {'x': 0.53501, 'y': 0.29786}, {'x': 0.53445, 'y': 0.30417}]} id_553_value_65_475.jpg 65.475 {'type': 'polygon', 'data': [{'x': 0.26133, 'y': 0.24071}, {'x': 0.31405, 'y': 0.23473}, {'x': 0.31741, 'y': 0.26688}, {'x': 0.30676, 'y': 0.26763}, {'x': 0.33985, 'y': 0.60851}, {'x': 0.29386, 'y': 0.61449}]} id_407_value_21_86.jpg 21.86 {'type': 'polygon', 'data': [{'x': 0.27545, 'y': 0.19134}, {'x': 0.37483, 'y': 0.18282}, {'x': 0.38935, 'y': 0.76071}, {'x': 0.28185, 'y': 0.76613}]}
转换逻辑
不管多边形包含多少个顶点,统一通过坐标极值计算最小外接矩形,再转换为YOLO要求的归一化格式,步骤如下:
- 解析字符串格式的标注字段,提取多边形所有顶点的x、y坐标
- 计算x坐标的最小值
min_x、最大值max_x,y坐标的最小值min_y、最大值max_y - 推导YOLO格式所需参数:
- 检测框宽度:
width = max_x - min_x - 检测框高度:
height = max_y - min_y - 检测框中心点x坐标:
center_x = min_x + width/2 - 检测框中心点y坐标:
center_y = min_y + height/2
- 检测框宽度:
注:该数据集的坐标本身就是相对图像宽高的归一化值,无需再除以图像分辨率做二次转换
- 为每张图片生成同名的txt标注文件,按
类别ID 中心点x 中心点y 框宽度 框高度的格式写入参数即可
可直接运行的转换代码
对原始实现的参数顺序、写入逻辑做了修正,适配标准YOLO标注格式:
import pandas as pd import ast def polygon_to_yolo(csv_path, label_save_dir, class_id=0): """ 批量将CSV格式的多边形水表标注转换为YOLO检测格式txt标注 :param csv_path: 原始标注CSV文件路径 :param label_save_dir: 生成的txt标注文件存储目录 :param class_id: 表盘ROI类别对应的ID,单类别检测默认设为0 """ df = pd.read_csv(csv_path) for _, row in df.iterrows(): # 获取无后缀的文件名,用于生成同名txt标注 img_full_name = row['photo_name'] file_name = img_full_name.split('.')[0] # 解析字符串存储的多边形字典 poly_anno = ast.literal_eval(row['location']) points = poly_anno['data'] # 提取所有顶点的x、y坐标 x_coords = [p['x'] for p in points] y_coords = [p['y'] for p in points] # 计算最小外接矩形的YOLO格式参数 min_x, max_x = min(x_coords), max(x_coords) min_y, max_y = min(y_coords), max(y_coords) bbox_w = max_x - min_x bbox_h = max_y - min_y center_x = min_x + bbox_w / 2 center_y = min_y + bbox_h / 2 # 写入标注文件 with open(f"{label_save_dir}/{file_name}.txt", "w", encoding='utf-8') as f: f.write(f"{class_id} {center_x:.6f} {center_y:.6f} {bbox_w:.6f} {bbox_h:.6f}") # 函数调用示例 # polygon_to_yolo(csv_path='water_meter_labels.csv', label_save_dir='./dataset/labels/train')
内容的提问来源于stack exchange,提问作者Rima
相关产品推荐
相关产品推荐

