You need to enable JavaScript to run this app. 理解OpenCV单应性变换最小点集应用及转换结果异常排查
优惠活动
大模型
产品
解决方案
定价
更多

理解OpenCV单应性变换最小点集应用及转换结果异常排查

你的代码存在3个核心问题:
  • 齐次坐标构造错误:2D点扩展为齐次坐标时,第三个分量应为1,你设置为0会导致计算结果完全偏离预期
  • 未做齐次坐标归一化:单应性矩阵是尺度无关的3x3矩阵,与齐次坐标相乘后得到的结果需要除以最后一个维度的数值,才能得到正确的2D笛卡尔坐标,直接取前两位的结果是错的
  • 手动矩阵运算容易出维度匹配问题,更推荐直接调用OpenCV封装好的cv2.perspectiveTransform方法做坐标变换

修复后可运行代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

points = np.array([
    [675, 585],
    [675, 1722],
    [3155, 580],
    [3162, 1722],
], dtype=np.float32)
t_points = np.array([
    [0,0], 
    [0, 8.23], 
    [23.77, 0],
    [23.77, 8.23]
], dtype=np.float32)

# 测试点构造
pt = np.array([675, 580+(1722-580)/2], dtype=np.float32)
pt_test = np.array([0,8.23/2], dtype=np.float32)

def get_h_matrix(src_list, dst_list):
    src_pts = src_list.reshape(-1,1,2)
    dst_pts = dst_list.reshape(-1,1,2)
    H, mask = cv2.findHomography(src_pts, dst_pts)
    return H

H = get_h_matrix(points, t_points)

# 手动矩阵运算的正确写法
pt_homogeneous = np.append(pt, 1) # 齐次坐标第三个分量设为1
transformed_h = H @ pt_homogeneous
transformed = transformed_h[:2] / transformed_h[2] # 归一化得到笛卡尔坐标

# 也可以直接调用OpenCV内置方法,更简便不易出错
# transformed = cv2.perspectiveTransform(pt.reshape(-1,1,2), H)[0][0]

print(f"实际变换坐标:{transformed}")
print(f"理论目标坐标:{pt_test}")

plt.scatter(t_points[:,0], t_points[:,1], color = 'blue')
plt.scatter(transformed[0], transformed[1], color = 'orange')
plt.scatter(pt_test[0], pt_test[1], color = 'green')
plt.show()

plt.scatter(points[:,0], points[:,1], color = 'blue')
plt.scatter(pt[0],pt[1], color = 'orange')
plt.show()

运行后可以看到橙色点和绿色点几乎完全重合,仅有的微小误差来自你原始标注点的少量偏移(原始points中第一点y值为585、第三点y值为580,本身不是完全水平的)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 17:06:04