当前位置: 首页 > news >正文

opencv_c++学习(二十七)

一、单目相机模型

在这里插入图片描述
上图为针孔相机成像原理,蓝色坐标中的O即为镜头光心。成像原理与小孔成像相同。
在这里插入图片描述
单目相机映射关系如下:
在这里插入图片描述
将上式进行变换,就可以从三位空间映射到2维平面的公式。
在这里插入图片描述
相机的畸变公式如下:
在这里插入图片描述

二、模型投影函数

void cv:projectPoints ( InputArray objectPoints, InputArray rvec, InputArray tvec, InputArray cameraMatrix,InputArray distCoeffs,outputArray imagePolints, jacobian =, OutputArray naArray(), double aspectRatio = 0)

objectPoints:世界坐标系中3D点的三维坐标。
rvec:世界坐标系变换到相机坐标系的旋转向量。
tvec:世界坐标系变换到相机坐标系的平移向量。
cameraMatrix:相机的内参矩阵。
distCoeffs:相机的畸变系数矩阵。
imagcPoints:三维坐标点在像素坐标系中估计的坐标。
jacobian:可选输出的雅可比矩阵。
aspectRatio:是否固定“宽高比”参数标志。
本节应用案例如下:

int main() {//输入计算的内参矩阵和畸变矩阵(在相机厂家说明或者标定获得)Mat cameraMatrix = (Mat_<float>(3, 3) << 532.016297, 0, 332.172519,0, 531.565159, 233.388075,0, 0, 1);Mat distCoeffs = (Mat_<float>(1, 5) << -0.285188, 0.080097, 0.001274,0.002415, 0.106579);//图像相机坐标系与世界坐标系之间的关系Mat rvec = (Mat_<float>(1, 3) << -1.977853, -2.002220, 0.130029);Mat tvec = (Mat_<float>(1, 3) << -26.88155, -42.79936, 159.19703);//生成第一张图像中内角点的三位世界坐标Size boardSize = Size(9,6);//棋盘格每个方格的真实尺寸Size squareSize = Size(10, 10);vector<Point3f> PointSets;for (int j = 0; j < boardSize.height; j++){for (int k = 0; k < boardSize.width; k++){Point3f realPoint;//假设标定板为世界坐标系的Z平面,及z=0realPoint.x = j * squareSize.width;realPoint.y = k * squareSize.height;realPoint.z = 0;PointSets.push_back(realPoint);}}//根据三维坐标和相机与世界坐标系时间的关系估计内角点像素坐标vector<Point2f> imagePoints;projectPoints(PointSets, rvec, tvec, cameraMatrix, distCoeffs, imagePoints);for (int i = 0; i < imagePoints.size(); i++){cout << imagePoints[i] << endl;}waitKey(0);return 0;}

三、单目相机标定

标定原理:
在这里插入图片描述
从上图中可以看出,相机坐标系可以通过世界坐标系进行平移变换来得到。具体的变换矩阵如相机坐标系右侧的公式。
标定板的图例如下:
在这里插入图片描述
上图中为两种类型的标定板,左侧为常用标定板,在提取的时候是内角点。而右侧标定板中不存在内角点,所以我们提取的是每个圆的中心点。
内角点提取函数如下:

bool cv:.findChessboardCorners ( InputArray image, Size patternSize, OutputArray corners, int flags = CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORNALIZE_IPAGE)

image:含有棋盘标定板的图像,图像必须是CV_8U的灰度图像或者彩色图像。
patternSize:图像中棋盘内角点行数和列数
corners:检测到的角点坐标
flags:检测角点方式的标志
圆形标定板中心提取:

bool cv::findCirclesGrid ( InputArray image, Size patternSize, OutputArray centers, int flags, const Ptr< FeatureDetector > & blolbDetector, const CirclesGridFinderParameters & parameters)

image:输入含有圆形网格的图像,图像必须是CV_8U的灰度图像或者彩色图像。
patternSize:图像中每行和每列圆形的数目。
corners:输出的圆形中心坐标。
flags:检测圆心的操作标志。
blobDetector:在浅色背景中寻找黑色圆形斑点的特征探测器。
角点位置优化函数:

bool cv.find4QuadCornerSubpix ( InputArray img, InputOutputArray corners, size region_size)

img:计算出内角点的图像。
patternSize:内角点坐标。
corners:优化坐标时考虑的邻域范围。

绘制内角点提取的结果:

void cv::drawChessboardCorners ( InputOutputArray image, size patternSize, InputArray corners, bool patternWasFound)

image:需要绘制角点的目标图像,必须是CU_8U的彩色图像。patternSize:标定板每行和每列角点的数目。
corners:检测到的角点坐标数组。
pattern WasFound:是否显示找到完成的标定板标志。

相机标定函数:

double cv::calibrateCamera ( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,Size imageSize, InputOutputArray cameraMatrix, InputoutputArray distCoeffs, OutputArrayOfArrays     rvecs, OutputArrayOfArrays tvecs,int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,30,DBL_EPSILON)

objectPoints:棋盘格内角点的三维坐标。
imagePoints:棋盘格内角点在图像中的二维坐标。
imageSize:图像的像素尺寸大小。
cameraMatrix:相机的内参矩阵。
distCoeffs:相机的畸变系数矩阵。
rvecs:相机坐标系与世界坐标系之间的旋转向量。
tvecs:相机坐标系与世界坐标系之间的平移向量。
flags:选择标定算法的标志。
本节应用案例如下:
本案例中采用了两张标定板的提取图像:
在这里插入图片描述
在这里插入图片描述
并将两个图片的路径存放到ca.txt文件中
在这里插入图片描述

int main() {//读取图像vector<Mat>imgs;string imgName;//读取存放图片路径的txt文件ifstream fin("ca.txt");//挨个读取图片while(getline(fin, imgName)){Mat img = imread(imgName);imgs.push_back(img);}//方格标定板内角点的数目(行,列)Size board_size = Size(9, 6);//存放内角点坐标vector<vector<Point2f>> imgsPoints;//开始内角点提取for (int i = 0; i < imgs.size(); i++){Mat img1 = imgs[i];Mat gray1;cvtColor(img1, gray1, COLOR_BGR2GRAY);vector<Point2f> img1_points;//计算标定板的角点findChessboardCorners(gray1, board_size, img1_points);//细化方格标定板角点坐标find4QuadCornerSubpix(gray1, img1_points, Size(5, 5));bool pattern = true;drawChessboardCorners(img1, board_size, img1_points, pattern);namedWindow("img1", WINDOW_NORMAL);imshow("img1", img1);waitKey(0);imgsPoints.push_back(img1_points);}//生成每个内角点的空间坐标Size squareSize = Size(10, 10);vector<vector<Point3f>> objectPoints;for (int i = 0; i < imgsPoints.size(); i++){vector<Point3f> tempPointSet;for (int j = 0; j < board_size.height; j++){for (int k = 0; k < board_size.width; k++){Point3f realPoint;//设标定板为世界坐标系的z平面,即z=0realPoint.x = j * squareSize.width;realPoint.y = k * squareSize.height;realPoint.z = 0;tempPointSet.push_back(realPoint);}}objectPoints.push_back(tempPointSet);}//图像尺寸Size imageSize;imageSize.width = imgs[0].cols;imageSize.height = imgs[0].rows;//摄像机内参数矩阵Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));//摄像机的5个畸变系数:k1,k2,p1,p2,k3Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));//每幅图像的旋转向量、平移量vector<Mat>  rvecs, tvecs;calibrateCamera(objectPoints, imgsPoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, 0);cout << "相机的内参矩阵:" << cameraMatrix << endl;cout << "相机畸变系数:" << distCoeffs << endl;waitKey(0);return 0;
}

最终的运行结果如下图:
在这里插入图片描述
这里只放一张图像。最终的输出结果为:

相机的内参矩阵:[120.8643306554273, 0, 94.55565247064737;0, 119.979406894919, 55.48571212317609;0, 0, 1]
相机畸变系数:[-0.5559208449775317, 3.15840209023594, -0.001816753642197531, -0.01817901488786, -7.629569308066959]

四、图像矫正

在这里插入图片描述
如上图(左)可以看出,相机采集的数据造成了一定的畸变,尤其是在边缘部分。

去畸变函数:

void cv::undistort ( InputArray src, OutputArray dst, InputArray cameraMatrix, InputArray  distCoeffs, InputArray newCameraMatrix = noArray())

src:含有畸变的输入图像。
dst:去畸变后的输出图像,与输入图像具有相同的尺寸和数据类型。
cameraMatrix:相机内参矩阵(上节中相机标定获得)。
distCoeffis:相机的畸变矩阵,根据近似模型不同,参数数量可以为4、5、8、12或者14,如果是空矩阵表示没有畸变。
newCameraMatrix:畸变图像的相机内参矩阵,一般情况下与第三个参数相同或者使用默认值。
本节应用案例如下:

//用undiststort()函数直接计算校正图像
void undist(vector<Mat> imgs, //原有图像向量Mat cameraMatrix, //计算得到的相机内存Mat distCoeffs, //计算得到的相机畸变系数vector<Mat> &undistImgs //校正后的输出图像
)
{for (int i = 0; i < imgs.size(); i++){Mat undisImg;undistort(imgs[i], undistImgs, cameraMatrix, distCoeffs);undistImgs.push_back(undisImg);}
}int main() {//读取图像vector<Mat>imgs;string imgName;//读取存放图片路径的txt文件ifstream fin("ca.txt");//挨个读取图片while (getline(fin, imgName)){Mat img = imread(imgName);imgs.push_back(img);}//输入计算的内参矩阵和畸变矩阵(在相机厂家说明或者标定获得)Mat cameraMatrix = (Mat_<float>(3, 3) << 120.8643306554273, 0, 94.55565247064737,0, 119.979406894919, 55.48571212317609,0, 0, 1);Mat distCoeffs = (Mat_<float>(1, 5) << -0.5559208449775317, 3.15840209023594, -0.001816753642197531, -0.01817901488786, -7.629569308066959);//去畸变图像存放变量vector<Mat> undistImags;Size imageSize;imageSize.width = imgs[0].cols;imageSize.height = imgs[0].rows;undist(imgs, cameraMatrix, distCoeffs, undistImags);//显示校正后的图像for (int i = 0; i < imgs.size(); i++){string windowNumber = to_string(i);imshow("矫正后的图像" + windowNumber, undistImags[i]);waitKey(0);destroyWindow("矫正后的图像" + windowNumber);}waitKey(0);return 0;
}

相关文章:

opencv_c++学习(二十七)

一、单目相机模型 上图为针孔相机成像原理&#xff0c;蓝色坐标中的O即为镜头光心。成像原理与小孔成像相同。 单目相机映射关系如下&#xff1a; 将上式进行变换&#xff0c;就可以从三位空间映射到2维平面的公式。 相机的畸变公式如下&#xff1a; 二、模型投影函数 vo…...

探查chatGPT插件:Outschool,resume,webhooks

引言 在我们的日常工作和学习中&#xff0c;插件扮演着重要的角色。它们可以帮助我们提高效率&#xff0c;简化复杂的任务。在这篇文章中&#xff0c;我将介绍三个非常有用的插件&#xff1a;Outschool&#xff0c;resume&#xff0c;和webhooks&#xff0c;并通过具体的例子来…...

【学习笔记】Unity基础(七)【uGUI基础、利用render Texture实现小地图功能】

目录 一 Canvas1.1 三种Render Space渲染空间 screen1.2 canvas scaler画布缩放器1.3sprite1.4 sprite packer1.5 unity目录1.6 RuleTile Tilemap1.7 sprite packer1.8 sorting layer 二 rect transform2.1 pivot 中轴 中心点2.2 anchor 锚点2.3 uGUI源代码 三 EventSystem3.1 …...

yolov5配置错误记录

这里是直接没有找到数据集&#xff0c;说明是路径错误。经过设置yaml后&#xff0c; # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..] path: ../autodl-tmp/datasets/neu # dataset root dir tr…...

全平台数据 (数据库) 管理工具 DataCap 1.10.0 发布

当前版本涉及几个主要更新。 DataCap 已发布 发布版本发布时间1.10.02023-05-30 General 修复服务启动默认连接 mongo修复了 sql 模板的 h2 db update_time 和 create_time改进 H2 元数据管理获取类型改进 mysql 元数据管理获取类型固定元数据管理数据页默认为 1重构数据渲染…...

使用Mybatis接口开发

文章目录 目录 前言 公司项目用到了mybatis开发接口,虽然很简单,但是mybatis不是特别熟悉,这里学习一下 一、Mybatis接口绑定的两种方式 1.接口绑定实现方式 就是在接口的方法上加上Select,updateInsertDelete等注解 select注解介绍: 简便,能快速去操作sql,它只需要在mapper…...

数据采集技术的实现原理有哪些?

数据采集技术是指通过各种手段和技术手段&#xff0c;从互联网、移动设备、传感器等各种数据源中获取数据&#xff0c;并将其存储、处理和分析&#xff0c;以便为业务决策和应用提供支持。本文将介绍数据采集技术的实现原理&#xff0c;包括数据采集的基本流程、数据采集技术的…...

2023年数学建模随机森林:基于多个决策树的集成学习方法

2023年9月数学建模国赛期间提供ABCDE题思路加Matlab代码,专栏链接(赛前一个月恢复源码199,欢迎大家订阅):http://t.csdn.cn/Um9Zd 目录 目录 1. 什么是随机森林? 2. 随机森林的优缺点 3. 随机森林的构建过程...

OpenAI发布最新研究让大模型数学推理直接达到SOTA

&#x1f989; AI新闻 &#x1f680; OpenAI发布最新研究&#xff1a;基于过程奖励的监督方法&#xff0c;让大模型数学推理直接达到SOTA 摘要&#xff1a;OpenAI最新研究基于GPT-4微调&#xff0c;采用过程监督和结果监督两种监督方法&#xff0c;奖励每个正确推理步骤的过程…...

快速检测 GlassFish 任意文件读取漏洞的 Python 脚本

部分数据来源:ChatGPT 引言 当下,互联网安全问题正愈发严重,黑客利用各种漏洞进行攻击的频率也在持续增加。在2015年10月,一位名为“路人甲”的安全研究员在乌云上公开了一个名为“应用服务器glassfish存在通用任意文件读取漏洞”的漏洞(编号:wooyun-2010-0144595),该…...

Docker镜像更新通知器DIUN

什么是 DIUN ? Docker Image Update Notifier 是一个用 Go 编写的 CLI 应用程序&#xff0c;可作为单个可执行文件和 Docker 映像交付&#xff0c;用于当 Docker 映像在 Docker registry中更新时接收通知。 和老苏之前介绍过的 watchtower 不同&#xff0c;DIUN 只是通知&…...

插件框架PF4J-从理论到实践

PF4J:Plugin Framework for Java 目录 是什么&#xff1f; 不是什么&#xff1f; 特点 组件 主要类 流程概述 spring-pf4j 思考 功能模块化 我对pf4j的封装和使用demo GitHub - chlInGithub/pf4jDemo: pf4j demo 是什么&#xff1f; 开源轻量级的插件框架。通过插件…...

怎么将pdf文件免费转为扫描件

推荐两个工具&#xff0c;也算是给自己记一下 1、手机&#xff1a;扫描全能王APP 太好使了&#xff0c;可以直接拍照并转换为扫描件 不开会员的话会出现水印&#xff0c;因为我都是自己用或者交作业就没开 支持读取相册&#xff0c;一次一张、多张都可以 如果不想要水印也…...

vue+nodejs校园二手物品交易市场网站_xa1i4

。为满足如今日益复杂的管理需求&#xff0c;各类管理系统程序也在不断改进。本课题所设计的校园二手交易市场&#xff0c;使用vue框架&#xff0c;Mysql数据库、nodejs语言进行开发&#xff0c;它的优点代码不能从浏览器查看&#xff0c;保密性非常好&#xff0c;比其他的管理…...

Barra模型因子的构建及应用系列六之Book-to-Price因子

一、摘要 在前期的Barra模型系列文章中&#xff0c;我们构建了Size因子、Beta因子、Momentum因子、Residual Volatility因子和NonLinear Size因子&#xff0c;并分别创建了对应的单因子策略&#xff0c;其中Size因子和NonLinear Siz因子具有很强的收益能力。本节文章将在该系列…...

【c语言习题】使用链表解决约瑟夫问题

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c语言系列专栏&#xff1a;c语言之路重点知识整合 &#x…...

JVM之类的初始化与类加载机制

类的初始化 clinit 初始化阶段就是执行类构造器方法clinit的过程。此方法不需定义&#xff0c;是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。构造器方法中指令按语句在源文件中出现的顺序执行。clinit不同于类的构造器。(关联&#xff1a;…...

面试专题:java 多线程(1)----synchronized关键字相关问答

在java 多线程 面试中最多问题1.悲观锁和乐观锁&#xff1b;2.synchronized和lock的区别&#xff1b;3.可重入锁和非可重入锁的区别&#xff1b;4.多线程是解决什么问题的&#xff1b;5.线程池解决什么问题的&#xff1b;6.线程池原理&#xff1b;7.线程池使用注意事项&#xf…...

VMware SD-WAN 5.2 发布 - 软件定义的 WAN

VMware SD-WAN 5.2 发布 - 软件定义的 WAN SD-WAN 解决方案的领导者 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-sd-wan-5/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 产品概述 软件定义的 WAN (SD-WAN)…...

Oracle+11g+RAC+PSU_EAM(2)

2.15 解压安装介质 在获取开篇1.2节中提到的安装介质如下&#xff1a; [rootebsrac1 ~]# ls -l -rw-r–r– 1 root root 1358454646 Apr 20 16:22 p13390677_112040_Linux-x86-64_1of7.zip -rw-r–r– 1 root root 1142195302 Apr 20 16:29 p13390677_112040_Linux-x86-64_…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...