OpenCV 与多视图几何

server/2024/10/20 4:07:05/

欢迎访问我的博客首页。

OpenCV 与多视图几何

  • 1. 工具函数
  • 2. 本质矩阵
  • 3. 单应矩阵
  • 4. 基础矩阵
  • 5. 参考

1. 工具函数


  像素坐标、归一化坐标和相机坐标之间的相互转化。

#include <iostream>
#include <opencv2/opencv.hpp>// 相机坐标系到像素坐标系的变换。
cv::Point2f cam2pix(const cv::Point3f &p, const cv::Mat &K) {return cv::Point2f((p.x * K.at<double>(0, 0)) / p.z + K.at<double>(0, 2), (p.y * K.at<double>(1, 1)) / p.z + K.at<double>(1, 2));
}// 像素坐标系到归一化成像平面的变换。
cv::Point2f pix2nor(const cv::Point2f &p, const cv::Mat &K) {return cv::Point2f((p.x - K.at<double>(0, 2)) / K.at<double>(0, 0), (p.y - K.at<double>(1, 2)) / K.at<double>(1, 1));
}// 相机坐标系到归一化成像平面的变换。
cv::Point2f cam2nor(const cv::Point3f &p, const cv::Mat &K) { return pix2nor(cam2pix(p, K), K); }// 相机坐标系到归一化成像平面的变换。
cv::Point2f cam2nor(const cv::Point3f &p) { return cv::Point2f(p.x / p.z, p.y / p.z); }int get_random_integer(int a = 10, int b = 100) { return rand() % (b - a + 1) + a; }

2. 本质矩阵


  本质矩阵利用匹配的像素坐标计算相机位姿关系。

int recoverPoseFromEssentialMat() {// 相机内参和外参。cv::Mat K = (cv::Mat_<double>(3, 3) << 521.0, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1);cv::Mat R = (cv::Mat_<double>(3, 3) << 0, 1, 0, -1, 0, 0, 0, 0, 1);cv::Mat t = (cv::Mat_<double>(3, 1) << 0, -1, 0);// 三维坐标。cv::Mat m1 = cv::Mat::zeros(3, 1, CV_32FC1);cv::Mat m2 = cv::Mat::zeros(3, 1, CV_32FC1);cv::Point3f p1;cv::Point3f p2;// 像素坐标。std::vector<cv::Point2d> pts1;std::vector<cv::Point2d> pts2;// 利用随机产生的三维坐标求像素坐标。srand((unsigned)time(NULL));for (int i = 0; i < 15; i++) {m1 = (cv::Mat_<double>(3, 1) << get_random_integer(), get_random_integer(), get_random_integer());m2 = R * m1 + t;p1 = cv::Point3f(cv::Point3f(m1.at<double>(0, 0), m1.at<double>(1, 0), m1.at<double>(2, 0)));p2 = cv::Point3f(cv::Point3f(m2.at<double>(0, 0), m2.at<double>(1, 0), m2.at<double>(2, 0)));pts1.push_back(cam2pix(p1, K));pts2.push_back(cam2pix(p2, K));}// 根据像素坐标求本质矩阵。cv::Mat mask;cv::Mat E = cv::findEssentialMat(pts1, pts2, K, cv::RANSAC, 0.99, 1.0);// 根据本质矩阵求位姿。cv::Mat rotation, translation;int inlier_count = cv::recoverPose(E, pts1, pts2, K, rotation, translation, mask);// 输出。std::cout << "-- 本质矩阵:" << std::endl;std::cout << inlier_count << std::endl << std::endl;std::cout << rotation << std::endl << std::endl;std::cout << translation.t() << std::endl;
}

3. 单应矩阵


  单应矩阵利用匹配的像素坐标计算相机位姿关系。

int recoverPoseFromHomographyMat() {// 相机内参和外参。cv::Mat K = (cv::Mat_<double>(3, 3) << 521.0, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1);cv::Mat R = (cv::Mat_<double>(3, 3) << 0, 1, 0, -1, 0, 0, 0, 0, 1);cv::Mat t = (cv::Mat_<double>(3, 1) << 0, -1, 0);// 三维坐标。cv::Mat m1 = cv::Mat::zeros(3, 1, CV_32FC1);cv::Mat m2 = cv::Mat::zeros(3, 1, CV_32FC1);cv::Point3f p1;cv::Point3f p2;// 像素坐标。std::vector<cv::Point2d> pts1;std::vector<cv::Point2d> pts2;// 利用随机产生的三维坐标求像素坐标。srand((unsigned)time(NULL));for (int i = 0; i < 15; i++) {m1 = (cv::Mat_<double>(3, 1) << get_random_integer(), get_random_integer(), get_random_integer());m2 = R * m1 + t;p1 = cv::Point3f(cv::Point3f(m1.at<double>(0, 0), m1.at<double>(1, 0), m1.at<double>(2, 0)));p2 = cv::Point3f(cv::Point3f(m2.at<double>(0, 0), m2.at<double>(1, 0), m2.at<double>(2, 0)));pts1.push_back(cam2pix(p1, K));pts2.push_back(cam2pix(p2, K));}// 根据像素坐标求单应矩阵。cv::Mat mask;cv::Mat H = cv::findHomography(pts1, pts2, cv::RANSAC);// 根据单应矩阵求位姿。std::vector<cv::Mat> rotations, translations, normals;int pose_count = cv::decomposeHomographyMat(H, K, rotations, translations, normals);assert(pose_count == rotations.size());// 输出。for (int i = 0; i < pose_count; i++) {std::cout << "-- 单应矩阵 " << i + 1 << "/" << pose_count << ":" << std::endl;std::cout << rotations[i] << std::endl << std::endl;std::cout << translations[i].t() << std::endl << std::endl;std::cout << normals[i].t() << std::endl << std::endl << std::endl;}
}

4. 基础矩阵


  基础矩阵利用匹配的归一化坐标计算相机位姿关系。参考 vins mono。

int recoverPoseFromFundamentalMat() {// 相机内参和外参。cv::Mat K = (cv::Mat_<double>(3, 3) << 521.0, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1);cv::Mat R = (cv::Mat_<double>(3, 3) << 0, 1, 0, -1, 0, 0, 0, 0, 1);cv::Mat t = (cv::Mat_<double>(3, 1) << 0, -1, 0);// 三维坐标。srand((unsigned)time(NULL));cv::Mat m1 = cv::Mat::zeros(3, 1, CV_32FC1);cv::Mat m2 = cv::Mat::zeros(3, 1, CV_32FC1);cv::Point3f p1;cv::Point3f p2;// 归一化坐标。std::vector<cv::Point2d> pts1;std::vector<cv::Point2d> pts2;// 利用随机产生的三维坐标求归一化坐标。for (int i = 0; i < 15; i++) {m1 = (cv::Mat_<double>(3, 1) << get_random_integer(), get_random_integer(), get_random_integer());m2 = R * m1 + t;p1 = cv::Point3f(cv::Point3f(m1.at<double>(0, 0), m1.at<double>(1, 0), m1.at<double>(2, 0)));p2 = cv::Point3f(cv::Point3f(m2.at<double>(0, 0), m2.at<double>(1, 0), m2.at<double>(2, 0)));pts1.push_back(cam2nor(p1));pts2.push_back(cam2nor(p2));}// 根据归一化坐标求基础矩阵。cv::Mat mask;cv::Mat F = cv::findFundamentalMat(pts1, pts2, cv::FM_RANSAC, 0.3 / 460, 0.99, mask);// 根据基础矩阵求位姿。cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);cv::Mat rotation, translation;int inlier_cnt = cv::recoverPose(F, pts1, pts2, cameraMatrix, rotation, translation, mask);// 输出。std::cout << "-- 基础矩阵:" << std::endl;std::cout << inlier_cnt << std::endl << std::endl;std::cout << rotation << std::endl << std::endl;std::cout << translation.t() << std::endl;
}

5. 参考


  1. 相机矩阵求解,CSDN。

http://www.ppmy.cn/server/99963.html

相关文章

前端工程化项目 用npm拉git项目的时候是在是太慢了怎么办

最近在家拉git项目发现npm i之后,开始下得挺快&#xff0c;过会就卡着不动了&#xff0c;大概几分钟后才下好。这对一个有强迫症的码农来说是不能容忍的。 只能退出去 重新下载 其实我们只要换一下国内的下载镜像源就好了 npm config set registry https://registry.npmmirror…

基于STM32开发的智能电能监测系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 家庭电能监测工业用电管理常见问题及解决方案 常见问题解决方案结论 1. 引言 智能电能监测系统通过实时采集电流、电压等电力参数&#xff0c;计算电能消耗&…

Java项目打包部署到服务器的详细教程

摘要&#xff1a;本文将详细介绍如何将Java项目打包成可执行文件&#xff0c;并将其部署到服务器上。通过本文的学习&#xff0c;你将掌握Java项目打包和部署的整个过程。 一、准备工作 开发环境&#xff1a;本文以IntelliJ IDEA为例&#xff0c;其他IDE同理。 服务器&#x…

mysql数据存储问题

目录 MySQL数据存储基础 MySQL数据存放位置 InnoDB存储引擎介绍 Mermaid图表&#xff1a;InnoDB存储引擎数据文件结构 表空间结构详解 组成要素 组织方式 页内组织 性能影响 Mermaid图表&#xff1a;表空间的层次化结构和页内组织 InnoDB行格式详解 行格式类型 Co…

Nginx异常关闭之中了挖矿病毒kswapd0

问题描述&#xff1a;系统突然无法访问了&#xff0c;登录服务器看了一下是因为Nginx服务关闭&#xff0c;重启后过了几天仍然异常关闭 系统&#xff1a;CentOS 7&#xff0c;Nginx 1.20 尝试解决过程&#xff1a;1、查询nginx/logs/error.log、系统日志&#xff0c;都没有查…

下一代 RAG 技术来了!微软正式开源 GraphRAG

省流总结 优点&#xff1a;检索准确度高 缺点&#xff1a;单个19w字构建用时4分30s、gpt4 token花费12美元 概述 7 月 2 日&#xff0c;微软开源了 GraphRAG&#xff0c;一种基于图的检索增强生成 (RAG) 方法&#xff0c;可以对私有或以前未见过的数据集进行问答。在 GitHub…

利用EditPlus进行Json数据格式化

利用EditPlus进行Json数据格式化 git下载地址&#xff1a;https://github.com/michael-deve/CommonData-EditPlusTools.git (安装过editplus的直接将里面的json.js文件复制走就行) 命令&#xff1a;Cscript.exe /nologo “D:\Program Files (x86)\EditPlus 3\json.js” D:\P…

git合入另一个分支连续的多个提交

例如&#xff0c;如果您想合入另一个分支feature-branch上的三个连续提交&#xff0c;其哈希值分别是commit1、commit2和commit3&#xff0c;您可以这样做&#xff1a; git checkout master # 切换到master分支 git cherry-pick commit1 commit2 commit3 # 将这些提交应用到当…