【cv::triangulatePoints】其中的投射矩阵P(3x4)是怎么得到的?(内外参数K[R|t]到最终矩阵的变换过程)

1. cv::triangulatePoints

cv::triangulatePoints 是 OpenCV 中用于三角测量的函数,用于从两个视角的图像点计算出对应的三维空间点。这在立体视觉和计算机视觉中非常有用,尤其是在从多视角图像中恢复三维结构时。

函数声明

cpp 复制代码
void cv::triangulatePoints(
    const cv::Mat& projMatrix1,
    const cv::Mat& projMatrix2,
    const cv::Mat& projPoints1,
    const cv::Mat& projPoints2,
    cv::Mat& points4D
);

参数解释

  • projMatrix1: 第一个视角的投影矩阵(3x4),描述了从三维空间到第一视角图像的映射关系。可以通过相机内参和外参来构造。
  • projMatrix2: 第二个视角的投影矩阵(3x4),描述了从三维空间到第二视角图像的映射关系。
  • projPoints1 : 第一个视角图像中的点坐标集合,类型通常为 cv::Mat,每个点为一个 2D 坐标。大小为 2xN,N 为点的数量。
  • projPoints2 : 第二个视角图像中的点坐标集合,类型与 projPoints1 相同,大小也为 2xN
  • points4D : 输出的四维点集合,类型为 cv::Mat。每个点表示为四维齐次坐标 (X, Y, Z, W),其中 W 通常是 1。大小为 4xN,N 为点的数量。

使用示例

以下是一个使用 cv::triangulatePoints 的示例:

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

int main() {
    // 第一个视角的投影矩阵(示例值)
    cv::Mat projMatrix1 = (cv::Mat_<double>(3, 4) << 
        1000, 0, 320, 0,
        0, 1000, 240, 0,
        0, 0, 1, 0);

    // 第二个视角的投影矩阵(示例值)
    cv::Mat projMatrix2 = (cv::Mat_<double>(3, 4) << 
        1000, 0, 320, -100,
        0, 1000, 240, 0,
        0, 0, 1, 0);

    // 第一个视角中的点
    cv::Mat projPoints1 = (cv::Mat_<double>(2, 2) << 
        100, 150,
        200, 250);

    // 第二个视角中的点
    cv::Mat projPoints2 = (cv::Mat_<double>(2, 2) << 
        110, 160,
        210, 260);

    // 输出的四维点
    cv::Mat points4D;

    // 执行三角测量
    cv::triangulatePoints(projMatrix1, projMatrix2, projPoints1, projPoints2, points4D);

    // 打印三维点
    for (int i = 0; i < points4D.cols; ++i) {
        cv::Mat point = points4D.col(i);
        double X = point.at<double>(0) / point.at<double>(3);
        double Y = point.at<double>(1) / point.at<double>(3);
        double Z = point.at<double>(2) / point.at<double>(3);
        std::cout << "3D Point: (" << X << ", " << Y << ", " << Z << ")\n";
    }

    return 0;
}

使用细节

  • 投影矩阵 : projMatrix1projMatrix2 是 3x4 的矩阵,通常由相机的内参矩阵和外参矩阵组合得到。它们表示从三维空间到两个视角图像的映射关系。
  • 点的格式 : projPoints1projPoints2 必须是相同大小的点集合,每个点都是二维坐标 (x, y)
  • 四维点 : points4D 输出的点是四维齐次坐标,其中最后一维 W 通常是 1。计算实际的三维点坐标时,需要将齐次坐标除以 W

2. 由KR\|t 得到映射矩阵P

要将相机投影矩阵 P P P写成 K R ∣ t \mathbf{K}\\mathbf{R} \| \\mathbf{t} KR∣t的形式,并将其变换为一个 3 × 4 3 \times 4 3×4的矩阵,我们需要分别处理相机的内参矩阵 K \mathbf{K} K和外参矩阵 R ∣ t \\mathbf{R} \| \\mathbf{t} R∣t

1. 相机内参矩阵 K \mathbf{K} K

相机内参矩阵 K \mathbf{K} K是一个 3 × 3 3 \times 3 3×3的矩阵,描述相机的内部参数:

K = f x 0 c x 0 f y c y 0 0 1 \mathbf{K} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} K= fx000fy0cxcy1

其中:

  • f x f_x fx和 f y f_y fy是焦距,单位通常是像素。
  • c x c_x cx和 c y c_y cy是主点(光心)的坐标。

2. 相机外参矩阵 R ∣ t \\mathbf{R} \| \\mathbf{t} R∣t

相机外参矩阵由旋转矩阵 R \mathbf{R} R和平移向量 t \mathbf{t} t组成,它是一个 3 × 4 3 \times 4 3×4的矩阵:

  • 旋转矩阵 R \mathbf{R} R 是一个 3 × 3 3 \times 3 3×3的矩阵,用于将三维点从世界坐标系旋转到相机坐标系:

R = R 11 R 12 R 13 R 21 R 22 R 23 R 31 R 32 R 33 \mathbf{R} = \begin{bmatrix} R_{11} & R_{12} & R_{13} \\ R_{21} & R_{22} & R_{23} \\ R_{31} & R_{32} & R_{33} \end{bmatrix} R= R11R21R31R12R22R32R13R23R33

  • 平移向量 t \mathbf{t} t 是一个 3 × 1 3 \times 1 3×1的向量,用于将旋转后的点从世界坐标系平移到相机坐标系:

t = t x t y t z \mathbf{t} = \begin{bmatrix} t_x \\ t_y \\ t_z \end{bmatrix} t= txtytz

  • 组合外参矩阵 :将 R \mathbf{R} R和 t \mathbf{t} t组合为一个 3 × 4 3 \times 4 3×4的矩阵:

R ∣ t = R 11 R 12 R 13 t x R 21 R 22 R 23 t y R 31 R 32 R 33 t z \\mathbf{R} \| \\mathbf{t} = \begin{bmatrix} R_{11} & R_{12} & R_{13} & t_x \\ R_{21} & R_{22} & R_{23} & t_y \\ R_{31} & R_{32} & R_{33} & t_z \end{bmatrix} R∣t= R11R21R31R12R22R32R13R23R33txtytz

3. 组合内参和外参矩阵

相机投影矩阵 P P P是内参矩阵 K \mathbf{K} K和外参矩阵 R ∣ t \\mathbf{R} \| \\mathbf{t} R∣t的乘积,结果是一个 3 × 4 3 \times 4 3×4的矩阵:

P = K R ∣ t \mathbf{P} = \mathbf{K}\\mathbf{R} \| \\mathbf{t} P=KR∣t

将它们进行矩阵乘法:

P = f x 0 c x 0 f y c y 0 0 1 R 11 R 12 R 13 t x R 21 R 22 R 23 t y R 31 R 32 R 33 t z \mathbf{P} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} R_{11} & R_{12} & R_{13} & t_x \\ R_{21} & R_{22} & R_{23} & t_y \\ R_{31} & R_{32} & R_{33} & t_z \end{bmatrix} P= fx000fy0cxcy1 R11R21R31R12R22R32R13R23R33txtytz

通过矩阵乘法,可以得到:

P = f x R 11 + c x R 31 f x R 12 + c x R 32 f x R 13 + c x R 33 f x t x + c x t z f y R 21 + c y R 31 f y R 22 + c y R 32 f y R 23 + c y R 33 f y t y + c y t z R 31 R 32 R 33 t z \mathbf{P} = \begin{bmatrix} f_x R_{11} + c_x R_{31} & f_x R_{12} + c_x R_{32} & f_x R_{13} + c_x R_{33} & f_x t_x + c_x t_z \\ f_y R_{21} + c_y R_{31} & f_y R_{22} + c_y R_{32} & f_y R_{23} + c_y R_{33} & f_y t_y + c_y t_z \\ R_{31} & R_{32} & R_{33} & t_z \end{bmatrix} P= fxR11+cxR31fyR21+cyR31R31fxR12+cxR32fyR22+cyR32R32fxR13+cxR33fyR23+cyR33R33fxtx+cxtzfyty+cytztz

解释

  • 第一行 :表示在 x 方向的投影,结合了 x 焦距 f x f_x fx、主点 c x c_x cx,以及旋转和平移的影响。
  • 第二行 :表示在 y 方向的投影,结合了 y 焦距 f y f_y fy、主点 c y c_y cy,以及旋转和平移的影响。
  • 第三行:用于齐次坐标的归一化。

总结

通过内参矩阵和外参矩阵的组合,我们得到了用于描述三维点到二维图像平面投影的投影矩阵 P \mathbf{P} P。这个矩阵在多视图几何和计算机视觉的应用中至关重要,特别是在三维重建和相机校准中。

相关推荐
c238564 小时前
C/C++每日一练6
c语言·c++·算法
念恒123064 小时前
网络基础
linux·网络·c++
mct1234 小时前
c++ iconv 字符utf-8转换gb2312失败
开发语言·c++
ziguo11225 小时前
Windows API 文件操作超级指南——从入门到内核
c++·windows·visualstudio
zhangfeng11337 小时前
Ascendc 大语言模型框架 AscendCraft 和pypto 的区别 pypto生成算子c++源码吗
c++·人工智能·语言模型·算子开发
一只小灿灿7 小时前
C++ 修饰符全面详解
开发语言·c++
code_pgf7 小时前
C/C++ 中 `typedef` 关键字详解
c语言·c++
会周易的程序员8 小时前
js-shm: 高性能 Node.js 共享内存模块
开发语言·javascript·c++·node.js·共享内存·shm
2023自学中8 小时前
imx6ull 开发板 贪吃蛇, C++11 SDL2 无硬件GPU优化版
linux·c++
科技大视界8 小时前
TikTok广告素材投放工具:从官方后台到AIGC一体化矩阵构建高效投放矩阵
人工智能·矩阵·aigc