首页 > 其他分享 >OpenCV获取相机旋转矩阵和平移矩阵

OpenCV获取相机旋转矩阵和平移矩阵

时间:2023-04-07 23:11:41浏览次数:49  
标签:平移 std image 矩阵 OpenCV vector cv points

想要求解旋转矩阵和平移矩阵,先要了解相机内参矩阵和畸变矩阵如何获取,不了解的可以先移步https://www.cnblogs.com/nobodyx/p/17297074.html


先上代码

#include <iostream>
#include <vector>
#include <glob.h>
#include <opencv2/opencv.hpp>

int main() {
    // 使用 glob 库读取棋盘格图片
    std::vector<cv::String> filenames;
    cv::glob("left*.jpg", filenames, false);

    // 初始化棋盘格的行列数和尺寸(单位:mm)
    cv::Size board_size(9, 6);
    float square_size = 20.f;

    // 存储棋盘格图像上所有角点坐标
    std::vector<std::vector<cv::Point3f>> object_points;
    std::vector<std::vector<cv::Point2f>> image_points;

    // 遍历所有棋盘格图片,检测角点并存储角点坐标
    for (const auto &filename : filenames) {
        cv::Mat image = cv::imread(filename, cv::IMREAD_GRAYSCALE);
        std::vector<cv::Point2f> corners;
        bool ret = cv::findChessboardCorners(image, board_size, corners);
        if (ret) {
            cv::cornerSubPix(image, corners, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.1));
            std::vector<cv::Point3f> object_point;
            for (int i = 0; i < board_size.height; ++i) {
                for (int j = 0; j < board_size.width; ++j) {
                    object_point.emplace_back(float(j * square_size), float(i * square_size), 0);
                }
            }
            object_points.emplace_back(object_point);
            image_points.emplace_back(corners);
        } else {
            std::cerr << "Failed to detect corners in image: " << filename << std::endl;
        }
    }

    // 计算相机内参矩阵和畸变矩阵
    cv::Mat camera_matrix, dist_coeffs;
    std::vector<cv::Mat> rvecs, tvecs;
    double rms = cv::calibrateCamera(object_points, image_points, cv::Size(1920, 1080), camera_matrix, dist_coeffs, rvecs, tvecs);

    // 打印相机内参矩阵和畸变矩阵
    std::cout << "Camera matrix:" << std::endl << camera_matrix << std::endl;
    std::cout << "Distortion coefficients:" << std::endl << dist_coeffs << std::endl;

    // 计算相机的旋转矩阵和平移矩阵
    cv::Mat rotation_matrix, translation_matrix;
    cv::solvePnP(object_points[0], image_points[0], camera_matrix, dist_coeffs, rotation_matrix, translation_matrix);

    // 打印相机的旋转矩阵和平移矩阵
    std::cout << "Rotation matrix:" << std::endl << rotation_matrix << std::endl;
    std::cout << "Translation matrix:" << std::endl << translation_matrix << std::endl;

    std::cout << std::endl;

    return 0;
}

头一次没有使用using namespace, 有点费劲


这里有必要解释一下一个关键的函数--solvePnP

cv::solvePnP(object_points, image_points, camera_matrix, dist_coeffs, rotation_vector, translation_vector, use_extrinsic_guess, flags);
  • object_points: std::vectorcv::Point3f 类型,存储 3D 物体坐标点的坐标值;
  • image_points: std::vectorcv::Point2f 类型,存储对应的 2D 图像坐标点的坐标值;
  • camera_matrix: cv::Mat 类型,相机的内参矩阵;
  • dist_coeffs: cv::Mat 类型,相机的畸变矩阵;
  • rotation_vector: cv::Mat 类型,函数返回的旋转向量,包含相机的旋转信息;
  • translation_vector: cv::Mat 类型,函数返回的平移向量,包含相机的平移信息;
  • use_extrinsic_guess: bool 类型,表示是否使用函数提供的外参估计结果作为初始值;
  • flags: int 类型,表示求解过程的选项,可选项包括 SOLVEPNP_ITERATIVE、SOLVEPNP_P3P、SOLVEPNP_EPNP 和 SOLVEPNP_DLS。

其中,rotation_vector 和 translation_vector 分别是 Rodrigues 变换和欧拉旋转的等效表示方式。可以通过 cv::Rodrigues(rotation_vector, rotation_matrix) 函数将旋转向量转换为旋转矩阵,或者通过 cv::composeRT(rotation_vector, translation_vector, camera_rotation, camera_translation, camera_rotation_matrix, camera_translation_matrix) 函数将旋转向量和平移向量组合成变换矩阵。


最后说一下思路

(1)求内参矩阵和畸变矩阵

// 使用 glob 库读取棋盘格图片
    std::vector<cv::String> filenames;
    cv::glob("left*.jpg", filenames, false);

    // 初始化棋盘格的行列数和尺寸(单位:mm)
    cv::Size board_size(9, 6);
    float square_size = 20.f;

    // 存储棋盘格图像上所有角点坐标
    std::vector<std::vector<cv::Point3f>> object_points;
    std::vector<std::vector<cv::Point2f>> image_points;

    // 遍历所有棋盘格图片,检测角点并存储角点坐标
    for (const auto &filename : filenames) {
        cv::Mat image = cv::imread(filename, cv::IMREAD_GRAYSCALE);
        std::vector<cv::Point2f> corners;
        bool ret = cv::findChessboardCorners(image, board_size, corners);
        if (ret) {
            cv::cornerSubPix(image, corners, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.1));
            std::vector<cv::Point3f> object_point;
            for (int i = 0; i < board_size.height; ++i) {
                for (int j = 0; j < board_size.width; ++j) {
                    object_point.emplace_back(float(j * square_size), float(i * square_size), 0);
                }
            }
            object_points.emplace_back(object_point);
            image_points.emplace_back(corners);
        } else {
            std::cerr << "Failed to detect corners in image: " << filename << std::endl;
        }
    }

    // 计算相机内参矩阵和畸变矩阵
    cv::Mat camera_matrix, dist_coeffs;
    std::vector<cv::Mat> rvecs, tvecs;
    double rms = cv::calibrateCamera(object_points, image_points, cv::Size(1920, 1080), camera_matrix, dist_coeffs, rvecs, tvecs);

    // 打印相机内参矩阵和畸变矩阵
    std::cout << "Camera matrix:" << std::endl << camera_matrix << std::endl;
    std::cout << "Distortion coefficients:" << std::endl << dist_coeffs << std::endl;

这个我不过多解释,不懂的可以看一下我上一篇博客

(2)求解旋转矩阵和平移矩阵

    // 计算相机的旋转矩阵和平移矩阵
    cv::Mat rotation_matrix, translation_matrix,R;
    cv::solvePnP(object_points[0], image_points[0], camera_matrix, dist_coeffs, R, translation_matrix );

    cv::Rodrigues(R, rotation_matrix);

    // 打印相机的旋转矩阵和平移矩阵
    std::cout << "Rotation matrix:" << std::endl << rotation_matrix << std::endl;
    std::cout << "Translation matrix:" << std::endl << translation_matrix << std::endl;

    std::cout << std::endl;

过程比较简单,就是用solvePnP获得相机旋转向量和平移向量,再利用Rodrigues把旋转向量转化为旋转矩阵,而平移向量和平移矩阵一致,直接打印即可。

标签:平移,std,image,矩阵,OpenCV,vector,cv,points
From: https://www.cnblogs.com/nobodyx/p/17297244.html

相关文章

  • python opencv line
    pythonopencvline importcv2#Loadanimageimg=cv2.imread("image1.jpg")#Drawaredlinefrom(0,0)to(100,100)withathicknessof5pixelscv2.line(img,(0,0),(100,100),(0,0,255),5)#Displaytheimagecv2.imshow("Im......
  • OpenCV获取相机的内参矩阵和畸变矩阵
    实验室任务要截止了,赶紧来上传一下学习成果,终极目的是获取视频每帧的旋转矩阵和平移矩阵,但没办法一口吃个胖子,所以先写一下相机内参矩阵和畸变矩阵的求解办法先上代码#include<opencv2/opencv.hpp>#include<iostream>#include<vector>usingnamespacecv;usingnamespace......
  • 用 Go 剑指 Offer 29. 顺时针打印矩阵
    给你一个m行n列的矩阵 matrix,请按照顺时针螺旋顺序,返回矩阵中的所有元素。 示例1:  输入:matrix=[[1,2,3],[4,5,6],[7,8,9]]输出:[1,2,3,6,9,8,7,4,5]示例2:  输入:matrix=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]输出:[1,2,3,4,8,12,11,10,9,5,6,7] 提示:m......
  • opencv-python 4.15. 基于分水岭算法的图像分割
    理论任何灰度图像都可以看作是地形表面,其中高强度表示峰和丘陵,而低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水的上升,取决于附近的峰值(梯度),来自不同山谷的水,明显具有不同的颜色将开始融合。为避免这种情况,你需要在水合并的位置建立障碍。你继续......
  • OpenCV图像像素读写操作
    常用类型介绍uchar类型typedefunsigneduint;typedefsignedcharschar;typedefunsignedcharuchar;typedefunsignedshortushort;Vec系列Vec+数字+字母:C++STLvector容器类似数字:Vec的长度字母:类型b:uchars:shortw:ushorti:intf:floatd:doubletypedefVec<uch......
  • UVA - 108 Maximum Sum 求子矩阵的最大和
    题目大意:给出一个矩阵,求出这个矩阵中的子矩阵的最大和解题思路:和UVA507的题目类似,只不过这次是个矩阵了,换个角度思考,将这个二维数组转换成一维数组思考,用sum存储该列的前N个数字的和,如,sum[3][1]就是第一列的前三个数字的和,这样就可以将其想象成一维的最大连续和了,在枚举行,求其最大的和......
  • opencv-python 4.14. 霍夫圆变换
    基础知识铺垫通过检索相关资料,学习到了霍夫圆检测的一点点皮毛知识,它的基本内容是认为图像上任何一个非零像素点,都有可能是一个潜在圆形上的一点。通过投票计算,生成累计坐标平面,然后在设置一个累计权重,去定位圆。在笛卡尔坐标系中圆的方程为(x-a)^2+(y-b)^2=r^2,其中(a,b......
  • 剑指 Offer 12. 矩阵中的路径
    题目链接:剑指Offer12.矩阵中的路径方法:DFS解题思路根据\(word\)中的第一个字母,从\(board\)网格中开始查找,通过\(DFS\)算法思想实现。注意:在每一轮开始查找前,每个位置的标记应该清除;每一个位置有上下左右四个方向可以选择;\(DFS\)查找进入下一步时要将位置标记......
  • 861. 翻转矩阵后的得分
    题目描述给了一个二维矩阵,矩阵的元素不是0就是1你可以进行任意次操作,让某行或者某列进行翻转元素的得分是每一行二进制的和问怎么操作可以让总得分最大?f1贪心+计算增量基本分析为啥可以贪心?(1)对每行来说,首位肯定是1最好,遮掩某些行需要翻转,某些不翻;(2)对同一列来说,大家的优先......
  • 题目 1024: [编程入门]矩阵对角线求和
    求一个3×3矩阵对角线元素之和。 解题思路和注意事项: 这道题还是蛮简单,首先要求求一个矩阵的主副对角线的元素和,那肯定要用到的就是多维数组。        多维数组的形式应该为:array[i][j]; 知道这个后我们开始分析题目:        先是主对角线,就是从左上到......