OpenCV相机标定与3D重建(25)计算两个三维点集之间的最优仿射变换矩阵(3x4)函数estimateAffine3D()的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

计算两个3D点集之间的最优仿射变换。

它计算 x y z = a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 X Y Z + b 1 b 2 b 3 \begin{bmatrix} x\\ y\\ z\\ \end{bmatrix} = \begin{bmatrix} a_{11} & a_{12} & a_{13}\\ a_{21} & a_{22} & a_{23}\\ a_{31} & a_{32} & a_{33}\\ \end{bmatrix} \begin{bmatrix} X\\ Y\\ Z\\ \end{bmatrix} + \begin{bmatrix} b_1\\ b_2\\ b_3\\ \end{bmatrix} xyz = a11a21a31a12a22a32a13a23a33 XYZ + b1b2b3

cv::estimateAffine3D 是 OpenCV 库中的一个函数,用于计算两个三维点集之间的最优仿射变换矩阵(3x4)。此函数通常用于3D图像配准、物体识别和追踪等领域。它通过最小化源点集与目标点集之间的几何误差来估计变换,并且可以选择使用鲁棒方法(如RANSAC)来处理异常值(outliers)。

函数原型

cpp 复制代码
int cv::estimateAffine3D
(
	InputArray 	src,
	InputArray 	dst,
	OutputArray 	out,
	OutputArray 	inliers,
	double 	ransacThreshold = 3,
	double 	confidence = 0.99 
)		

参数

src 第一个输入的3D点集,包含 (X,Y,Z) 坐标。

dst 第二个输入的3D点集,包含 (x,y,z) 坐标。

out 输出的3D仿射变换矩阵 3×4,形式如下:
a 11 a 12 a 13 b 1 a 21 a 22 a 23 b 2 a 31 a 32 a 33 b 3 \begin{bmatrix} a_{11} & a_{12} & a_{13} & b_1\\ a_{21} & a_{22} & a_{23} & b_2\\ a_{31} & a_{32} & a_{33} & b_3\\ \end{bmatrix} a11a21a31a12a22a32a13a23a33b1b2b3

inliers 输出向量,指示哪些点是内点(1-内点,0-外点)。

ransacThreshold 在RANSAC算法中,考虑一个点为内点的最大重投影误差。

confidence 对估计变换的置信水平,在0和1之间。通常0.95到0.99之间的值就足够了。过于接近1的值可能会显著减慢估计过程。低于0.8-0.9的值可能导致变换估计不准确。

该函数使用RANSAC算法估计两个3D点集之间的最优3D仿射变换。

代码示例

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

using namespace cv;
using namespace std;

int main()
{
    // 定义两组对应的3D点 (X, Y, Z) - 源点集和目标点集
    vector< Point3f > src = { Point3f( 0, 0, 0 ), Point3f( 1, 0, 0 ), Point3f( 0, 1, 0 ), Point3f( 0, 0, 1 ) };
    vector< Point3f > dst = { Point3f( 1, 1, 1 ), Point3f( 2, 1, 1 ), Point3f( 1, 2, 1 ), Point3f( 1, 1, 2 ) };

    // 定义一个 Mat 来接收输出的仿射变换矩阵
    Mat affineMatrix;

    // 定义一个 Mat 来接收内点信息
    vector< uchar > inliers;

    // 调用 estimateAffine3D 函数
    int inlierCount = estimateAffine3D( src, dst, affineMatrix, inliers );

    if ( !affineMatrix.empty() )
    {
        cout << "Estimated Affine Matrix:\n" << affineMatrix << endl;
        cout << "Number of inliers: " << inlierCount << endl;

        // 打印哪些点被认为是内点
        for ( size_t i = 0; i < inliers.size(); ++i )
        {
            if ( inliers[ i ] )
            {
                cout << "Point pair (" << src[ i ] << ", " << dst[ i ] << ") is an inlier.\n";
            }
            else
            {
                cout << "Point pair (" << src[ i ] << ", " << dst[ i ] << ") is an outlier.\n";
            }
        }
    }
    else
    {
        cout << "Failed to estimate affine transformation." << endl;
    }

    return 0;
}

运行结果

bash 复制代码
Estimated Affine Matrix:
[0.9999999999999998, 3.483324739761429e-15, -1.838806884535416e-15, 0.9999999999999998;
 -4.649058915617843e-16, 1.000000000000004, -1.595945597898663e-15, 1;
 -4.371503159461554e-16, 3.337607967779377e-15, 0.9999999999999983, 0.9999999999999994]
Number of inliers: 1
Point pair ([0, 0, 0], [1, 1, 1]) is an inlier.
Point pair ([1, 0, 0], [2, 1, 1]) is an inlier.
Point pair ([0, 1, 0], [1, 2, 1]) is an inlier.
Point pair ([0, 0, 1], [1, 1, 2]) is an inlier.
相关推荐
jinxindeep15 小时前
CVPR26最佳论文提名:SAM3D,单图生成可组合3D场景的基础模型
3d
无负今日_tq15 小时前
ESP32-S3 桌面语音移动机器人 DIY:可移动、可对话、带 OLED/RGB 和 3D 打印外壳
3d
毕安格 - BimAngle17 小时前
地理配准高级教程:局部坐标(无地理信息)模型篇
3d·cesium·gltf·glb·3d tiles
在水一缸18 小时前
深度解析:基于 3D Gaussian Splatting 技术的编辑器实践与原理
计算机视觉·3d·编辑器·aigc·3d建模·nerf·3d编辑器
君为先-bey18 小时前
CineMaster: 3D感知电影级视频生成框架文献深度阅读分析
3d·音视频·扩散模型
故渊at18 小时前
第一板块:Android 系统基石与运行原理 | 第五篇:Context 上下文与资源配置体系
android·人工智能·opencv·context·上下文·资源配置体系
ice81303318118 小时前
【Python】调用opencv识别图片人脸位置
人工智能·python·opencv
人工智能培训1 天前
打造行业知识图谱三步走
大数据·人工智能·机器学习·3d·知识图谱·agent
智海深蓝1 天前
数字孪生案例 | 某船舶重工集团研究所如何打造“节能减碳仿真可视化平台”
3d
C++ 老炮儿的技术栈2 天前
如何利用 OpenCV 将图像显示在对话框窗口上
c语言·c++·人工智能·qt·opencv·计算机视觉·github