单应性矩阵
单应性矩阵
1.1 核心概念
单应性矩阵处理的是平面到平面的变换问题。想象一张倾斜拍摄的文档照片,我们想要将其校正为正视图,这就是典型的单应性矩阵应用。
- 变换层级关系
平面变换的自由度从低到高、覆盖范围从窄到宽的层级为:
刚性变换(Rigid)⊂ 相似变换(Similarity)⊂ 仿射变换(Affine)⊂ 单应变换(Homography)⊂ 投影变换
- 矩阵形式的差异与联系
两者均用齐次坐标描述平面点的变换(平面点 \((x,y)\)表示为齐次坐标 \((x,y,1)\)),但矩阵的约束和自由度不同。
1.2 仿射变换矩阵(Affine)
维度:\(3 \times 3\) 矩阵,最后一行固定为 \([0, 0, 1]\)(无透视项)
数学形式:
变换公式:齐次坐标下,目标点\(p_1 =H_{affine} \cdot p\),展开为:
1.3 单应性矩阵(Homography)
维度:\(3 \times 3\) 矩阵,无固定行约束(包含透视项),且矩阵是齐次的(整体缩放不影响变换结果,通常归一化使最后一个元素为 1)
数学表达式:
其中:
- \(\mathbf{X} = (X, Y, 1)^T\) 是世界平面上的齐次坐标
- \(\mathbf{x} = (u, v, 1)^T\) 是图像平面上的齐次坐标
- "\(\sim\)" 表示比例相等(齐次坐标的性质)
展开形式:
其中单应矩阵H有几个自由度?
其实只有8个,因为这里使用的是齐次坐标系(可以进行任意尺度的缩放);比如把\(h_{ij}\)乘以任意一个非零常数k,并不会改变等式结果。
与上述等式是一样的。
1.4 求解方法
求解条件
- 至少需要4对不共线的对应点
- 每对点提供2个独立方程
- 单应性矩阵有8个自由度(尺度无关)
8自由度下H计算过程有两种方法:
- 直接设置\(h_{33} = 1\),那么上述等式变为:
- 将H添加约束条件,将H矩阵模变成1,如下:
将上述等式分别乘以分母展开,得到:
整理,得到:
那么可以得到如下线性方程组:
1.5 实际应用案例
场景:文档扫描校正
输入数据:
世界坐标系(A4纸角点,单位:毫米):
(0, 0), (210, 0), (210, 297), (0, 297)
图像坐标系(像素坐标):
(120, 150), (380, 160), (390, 520), (110, 510)
求解过程详解
第一步:构建完整系数矩阵
对于4个点,构建8×9的系数矩阵:
第二步:SVD分解求解
对矩阵 \(\mathbf{A}\) 进行奇异值分解:\(\mathbf{A} = \mathbf{U} \mathbf{\Sigma} \mathbf{V}^T\)
最小二乘解对应于 \(\mathbf{V}\) 的最后一列(最小奇异值对应的右奇异向量)。
第三步:获得单应性矩阵
通过SVD求解得到的向量(归一化后):
第四步:构建单应性矩阵
验证求解结果
测试点:世界坐标 (105, 148.5)(A4纸中心)
使用单应性矩阵变换:
重投影误差检查:
- 理论图像坐标:(198.79, 316.78)
- 实际检测坐标:(约200, 约320)
- 误差:\(\sqrt{(200-198.79)^2 + (320-316.78)^2} = \sqrt{1.46 + 10.37} = 3.44\)
1.6 编程调用
OpenCV 计算单应矩阵
OpenCV 中核心函数是 findHomography,支持最小二乘、RANSAC 等鲁棒算法,适配不同场景(如外点较多的情况)。
Mat findHomography(
InputArray srcPoints, // 源点集(至少4对不共线点,如vector<Point2f>)
InputArray dstPoints, // 目标点集(数量/顺序与源点一一对应)
int method = 0, // 计算方法:
// 0:默认,最小二乘(无鲁棒性,易受外点影响)
// RANSAC:鲁棒估计算法(推荐,可过滤外点)
// LMEDS:中值鲁棒估计
double ransacReprojThreshold = 3, // RANSAC重投影阈值(像素),超过则视为外点
OutputArray mask = noArray() // 输出掩码(内点=1,外点=0)
);
示例:
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// 1. 准备源点和目标点(示例:4对不共线点)
vector<Point2f> srcPoints = {
Point2f(10, 10), Point2f(100, 10),
Point2f(100, 100), Point2f(10, 100)
};
vector<Point2f> dstPoints = {
Point2f(20, 20), Point2f(110, 15),
Point2f(105, 110), Point2f(15, 105)
};
// 2. 计算单应矩阵(RANSAC鲁棒估计)
Mat H, mask;
H = findHomography(srcPoints, dstPoints, RANSAC, 3.0, mask);
Halcon 计算单应矩阵
Halcon 中计算单应矩阵分两种场景:
- 无鲁棒性(最小二乘):vector_to_hom_mat2d;
- 有鲁棒性(RANSAC 过滤外点):ransac_homography_2d(推荐)
// 最小二乘,无鲁棒性
vector_to_hom_mat2d( : : Row1, Column1, Row2, Column2 : HomMat2D)
// Row1/Column1:源点的行 / 列坐标(Halcon 中Row对应 y,Column对应 x,)
// Row2/Column2:目标点的行 / 列坐标;
// HomMat2D:输出 3x3 单应矩阵。

浙公网安备 33010602011771号