You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV将图像配准的单应性矩阵应用于COCO格式标注?

用Homography矩阵变换COCO格式标注的方法

核心原理

Homography是3×3的透视变换矩阵,对COCO标注里的2D坐标点(x,y),需要先转为齐次坐标(x,y,1),与矩阵相乘后再转回非齐次坐标:

[x', y', w'] = H · [x, y, 1]^T
x_new = x' / w'
y_new = y' / w'

OpenCV的cv2.perspectiveTransform可以批量处理点,比手动计算更高效。


一、处理多边形标注(COCO segmentation字段)

COCO的segmentation是一维列表格式:[x1,y1,x2,y2,...xn,yn],部分场景下会是多多边形的列表(如[[x1,y1...],[x2,y2...]])。

代码实现

import numpy as np
import cv2

def transform_polygon(polygon, homography):
    # 转换为OpenCV要求的(n,1,2)数组格式
    points = np.array(polygon).reshape(-1, 1, 2).astype(np.float32)
    # 应用单应性变换
    transformed_points = cv2.perspectiveTransform(points, homography)
    # 转回COCO需要的一维列表
    return transformed_points.flatten().tolist()

多多边形处理

如果标注包含多个多边形,遍历处理即可:

# 假设ann是COCO的单个annotation对象
if isinstance(ann['segmentation'][0], list):
    ann['segmentation'] = [transform_polygon(poly, homography) for poly in ann['segmentation']]
else:
    ann['segmentation'] = transform_polygon(ann['segmentation'], homography)

二、处理边界框标注(COCO bbox字段)

COCO的bbox格式为[x, y, width, height],其中(x,y)是框的左上角坐标。

通用处理方法(适配所有透视变换)

即使是轻微平移,也建议用这种方法覆盖潜在的微小旋转/缩放:

  1. 提取bbox的四个角点
  2. 变换所有角点
  3. 根据变换后的角点重新计算bbox的边界
def transform_bbox(bbox, homography):
    x, y, w, h = bbox
    # 定义bbox的四个角点
    corners = np.array([
        [x, y],
        [x + w, y],
        [x, y + h],
        [x + w, y + h]
    ], dtype=np.float32).reshape(-1, 1, 2)
    # 变换角点
    transformed_corners = cv2.perspectiveTransform(corners, homography)
    # 提取变换后的x、y坐标
    xs = transformed_corners[:, 0, 0]
    ys = transformed_corners[:, 0, 1]
    # 计算新的bbox参数
    new_x = np.min(xs)
    new_y = np.min(ys)
    new_w = np.max(xs) - new_x
    new_h = np.max(ys) - new_y
    # 返回COCO格式的bbox(可根据原标注类型转整数/保留浮点)
    return [new_x, new_y, new_w, new_h]

纯平移场景简化版

如果确认Homography是纯平移矩阵(形式为[[1,0,tx],[0,1,ty],[0,0,1]]),可以直接平移坐标:

def transform_bbox_translation_only(bbox, homography):
    tx = homography[0, 2]
    ty = homography[1, 2]
    x, y, w, h = bbox
    return [x + tx, y + ty, w, h]

三、批量处理COCO标注文件

遍历COCO json文件的所有标注,批量应用变换:

import json

def process_coco_annotations(input_json, homography, output_json):
    with open(input_json, 'r') as f:
        coco_data = json.load(f)
    
    for ann in coco_data['annotations']:
        # 处理多边形标注
        if 'segmentation' in ann and ann['segmentation']:
            if isinstance(ann['segmentation'][0], list):
                ann['segmentation'] = [transform_polygon(poly, homography) for poly in ann['segmentation']]
            else:
                ann['segmentation'] = transform_polygon(ann['segmentation'], homography)
        # 处理bbox标注
        if 'bbox' in ann and ann['bbox']:
            ann['bbox'] = transform_bbox(ann['bbox'], homography)
    
    # 保存处理后的标注
    with open(output_json, 'w') as f:
        json.dump(coco_data, f, indent=2)

注意事项

  1. 矩阵方向验证:确保Homography矩阵是从源图像到目标图像的变换(源点×H=目标点),如果方向反了,用cv2.invert(homography)[1]求逆矩阵。
  2. 坐标类型对齐:原标注如果是整数,变换后可通过round()+int()转换为整数,避免浮点坐标引发的问题。
  3. 结果验证:将变换后的标注绘制到目标图像上,检查是否与目标图像内容对齐。

内容的提问来源于stack exchange,提问作者Gabriele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:03:27