- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
将单应性矩阵分解为旋转矩阵、平移向量和法向量。
cv::decomposeHomographyMat 是 OpenCV 库中的一个函数,用于将单应性矩阵(Homography Matrix)分解为旋转矩阵(Rotation Matrices)、平移向量(Translation Vectors)和法向量(Normals)。该函数能够从给定的单应性矩阵中提取出多个可能的解,这些解描述了平面在两个不同视角之间的相对运动。
函数原型
cpp
int cv::decomposeHomographyMat
(
InputArray H,
InputArray K,
OutputArrayOfArrays rotations,
OutputArrayOfArrays translations,
OutputArrayOfArrays normals
)
参数
- 参数H:两个图像之间的输入单应性矩阵。
- 参数K:输入的相机内参矩阵。
- 参数rotations:旋转矩阵数组。
- 参数translations:平移向量数组(注意,这里应该是"平移向量"而非"平移矩阵")。
- 参数normals:平面法向量数组。
此函数提取平面物体在两个视图之间的相对相机运动,并返回最多四个由旋转、平移和平面法向量组成的数学解元组。单应性矩阵 H 的分解在文献 [176] 中有详细描述。
如果由平面诱导的单应性矩阵 H 给出了约束
[ x i ′ y i ′ 1 ] ∼ H [ x i y i 1 ] \begin{bmatrix} x'_i \\ y'_i \\ 1 \end{bmatrix} \sim H \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix} xi′yi′1 ∼H xiyi1
其中 H 是单应性矩阵,那么旋转数组 rotations[k] 和平移数组 translations[k] 组成的元组是从源相机坐标系到目标相机坐标系的基变换。然而,通过分解 H,只能获得由场景深度(通常是未知的)归一化的平移,即其方向但长度是归一化的。
如果有点对应关系可用,通过应用正深度约束(即所有点必须位于相机前方),至少可以排除两个解。
代码示例
cpp
#include <iostream>
#include <opencv2/opencv.hpp>
int main()
{
// 假设我们已经得到了单应性矩阵 H 和相机内参矩阵 K
cv::Mat H = ( cv::Mat_< double >( 3, 3 ) << 0.998, -0.062, 50, 0.062, 0.998, 100, 0.007, 0.05, 1 );
cv::Mat K = ( cv::Mat_< double >( 3, 3 ) << 500, 0, 320, 0, 500, 240, 0, 0, 1 );
// 创建输出容器
std::vector< cv::Mat > rotations;
std::vector< cv::Mat > translations;
std::vector< cv::Mat > normals;
// 分解单应性矩阵
int numSolutions = cv::decomposeHomographyMat( H, K, rotations, translations, normals );
// 打印结果
std::cout << "Number of solutions: " << numSolutions << "\n";
for ( int i = 0; i < numSolutions; ++i )
{
std::cout << "Solution " << i + 1 << ":\n";
std::cout << "Rotation Matrix:\n" << rotations[ i ] << "\n";
std::cout << "Translation Vector:\n" << translations[ i ] << "\n";
std::cout << "Normal Vector:\n" << normals[ i ] << "\n";
}
return 0;
}
运行结果
bash
Number of solutions: 4
Solution 1:
Rotation Matrix:
[-0.9802608247288047, 0.1889271965254338, 0.05826860145100454;
0.1697517542892211, 0.6531756122806627, 0.7379335752195324;
0.101356092158646, 0.7332585723559504, -0.6723531874309145]
Translation Vector:
[18.39045228566228;
11.99059679500396;
-29.81341238180146]
Normal Vector:
[0.1208936041858721;
0.8638372310213145;
0.4890500738864864]
Solution 2:
Rotation Matrix:
[-0.9802608247288047, 0.1889271965254338, 0.05826860145100454;
0.1697517542892211, 0.6531756122806627, 0.7379335752195324;
0.101356092158646, 0.7332585723559504, -0.6723531874309145]
Translation Vector:
[-18.39045228566228;
-11.99059679500396;
29.81341238180146]
Normal Vector:
[-0.1208936041858721;
-0.8638372310213145;
-0.4890500738864864]
Solution 3:
Rotation Matrix:
[-0.4626383896883119, 0.5400507693070011, -0.7030724620958111;
0.3419971927832055, -0.6229459442112031, -0.7035455001054416;
-0.8179264273239335, -0.5659359656001044, 0.1035028614299165]
Translation Vector:
[18.42326185348789;
13.79683557680836;
-29.00092162954408]
Normal Vector:
[0.09258217344711696;
0.8432401346969438;
0.5295041231152859]
Solution 4:
Rotation Matrix:
[-0.4626383896883119, 0.5400507693070011, -0.7030724620958111;
0.3419971927832055, -0.6229459442112031, -0.7035455001054416;
-0.8179264273239335, -0.5659359656001044, 0.1035028614299165]
Translation Vector:
[-18.42326185348789;
-13.79683557680836;
29.00092162954408]
Normal Vector:
[-0.09258217344711696;
-0.8432401346969438;
-0.5295041231152859]