OpenCV相机标定与3D重建(24)计算两个二维点集之间的最佳仿射变换矩阵(2x3)函数estimateAffine2D()的使用

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

算法描述

计算两个二维点集之间的最优仿射变换,它计算 [ x y ] = [ a 11 a 12 a 21 a 22 ] [ X Y ] + [ b 1 b 2 ] \begin{bmatrix} x\\ y\\ \end{bmatrix} = \begin{bmatrix} a_{11} & a_{12}\\ a_{21} & a_{22}\\ \end{bmatrix} \begin{bmatrix} X\\ Y\\ \end{bmatrix} + \begin{bmatrix} b_1\\ b_2\\ \end{bmatrix} [xy]=[a11a21a12a22][XY]+[b1b2]

cv::estimateAffine2D 是 OpenCV 库中的一个函数,用于计算两个二维点集之间的最佳仿射变换矩阵(2x3)。这个函数通常用于图像配准、物体识别和追踪等领域。它通过最小化从一个点集到另一个点集的几何误差来估计变换。

函数原型

cpp 复制代码
cv::Mat cv::estimateAffine2D
(
	InputArray 	from,
	InputArray 	to,
	OutputArray 	inliers = noArray(),
	int 	method = RANSAC,
	double 	ransacReprojThreshold = 3,
	size_t 	maxIters = 2000,
	double 	confidence = 0.99,
	size_t 	refineIters = 10 
)		

参数

  • 参数from 第一个输入的2D点集,包含 (X,Y) 坐标。
  • 参数to 第二个输入的2D点集,包含 (x,y) 坐标。
  • 参数inliers 输出向量,指示哪些点是内点(1-内点,0-外点)。
  • 参数method 用于计算变换的鲁棒方法。可能的方法包括:
    • RANSAC - 基于RANSAC的鲁棒方法
    • LMEDS - 最小中位数鲁棒方法
    • 默认方法为 RANSAC。
  • 参数ransacReprojThreshold 在RANSAC算法中,考虑一个点为内点的最大重投影误差。仅适用于RANSAC。
  • 参数maxIters 鲁棒方法的最大迭代次数。
  • 参数confidence 对估计变换的置信水平,在0和1之间。通常0.95到0.99之间的值就足够了。过于接近1的值可能会显著减慢估计过程。低于0.8-0.9的值可能导致变换估计不准确。
  • 参数refineIters 精化算法(Levenberg-Marquardt)的最大迭代次数。传递0将禁用精化,因此输出矩阵将是鲁棒方法的输出。

返回值

返回

输出2D仿射变换矩阵 2×3,如果无法估计变换则返回空矩阵。返回的矩阵具有以下形式:

a 11 a 12 b 1 a 21 a 22 b 2 \] \\begin{bmatrix} a_{11} \& a_{12} \& b_1\\\\ a_{21} \& a_{22} \& b_2\\\\ \\end{bmatrix} \[a11a21a12a22b1b2

该函数使用选定的鲁棒算法估计两个2D点集之间的最优2D仿射变换。

计算出的变换随后会进一步通过Levenberg-Marquardt方法进行精化(仅使用内点),以进一步减少重投影误差。

注释

RANSAC 方法实际上可以处理任意比例的外点,但需要一个阈值来区分内点和外点。LMeDS 方法不需要任何阈值,但它只有在内点超过50%的情况下才能正确工作。

代码示例

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

using namespace cv;
using namespace std;

int main()
{
    // 定义两组对应的点 (x, y) - 源点集和目标点集
    std::vector< Point2f > from = { Point2f( 0, 0 ), Point2f( 1, 0 ), Point2f( 0, 1 ), Point2f( 1, 1 ) };
    std::vector< Point2f > to   = { Point2f( 2, 2 ), Point2f( 3, 2 ), Point2f( 2, 3 ), Point2f( 3, 3 ) };

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

    // 调用 estimateAffine2D 函数
    Mat affineMatrix = estimateAffine2D( from, to, inliers );

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

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

    return 0;
}

运行结果

bash 复制代码
Estimated Affine Matrix:
[1, -0, 2;
 -0, 1, 2]
Point pair ([0, 0], [2, 2]) is an inlier.
Point pair ([1, 0], [3, 2]) is an inlier.
Point pair ([0, 1], [2, 3]) is an inlier.
Point pair ([1, 1], [3, 3]) is an inlier.
相关推荐
AndrewHZ4 小时前
【图像处理基石】暗光增强算法入门:从原理到实战(Python+OpenCV)
图像处理·python·opencv·算法·计算机视觉·cv·暗光增强
想看雪的瓜5 小时前
Origin绘制3D坐标下边际直方图
3d
接着奏乐接着舞。7 小时前
3D地球可视化教程 - 第3篇:地球动画与相机控制
前端·vue.js·3d·threejs
~光~~8 小时前
【环境配置 安装 】RK3588+Ubuntu20.04+cmake3.22+opencv4.54
opencv·ubuntu·rk3588
研梦非凡8 小时前
ShapeLLM: 用于具身交互的全面3D物体理解
人工智能·深度学习·计算机视觉·3d·架构·数据分析
txwtech21 小时前
第6篇 OpenCV RotatedRect如何判断矩形的角度
人工智能·opencv·计算机视觉
过往入尘土1 天前
走进 OpenCV 人脸识别的世界
人工智能·python·深度学习·opencv
二川bro1 天前
第28节:网络同步与多人在线3D场景
网络·3d
dlraba8022 天前
用 Python+OpenCV 实现实时文档扫描:从摄像头捕捉到透视矫正全流程
开发语言·python·opencv