相机标定-opencv单应性矩阵实现平面坐标标定(kinect v1)
opencv单应性矩阵实现平面坐标标定
- 说明
- 一、使用单应性矩阵的原因
- 二、标定原理
- 三、findHomography 函数与 getPerspectiveTransform函数的区别
- 1、两者联系
- 2、两者区别
- (1)计算方法不同
- (2)输入参数不同
- 四、代码实现
- 1、棋盘格下载地址
- 2、代码(c++)
- 3、结果
说明
1、使用Opencv的单应性矩阵实现平面上的相机参数标定
2、相机采用Kinect V1
一、使用单应性矩阵的原因
打算通过像素坐标得到对应物体在世界坐标系的三维坐标,但是得到旋转矩阵和平移向量后,内外参相乘,接着用三维坐标去还原二维坐标,得到的跟实际二维坐标相差甚远。
所以最后打算不分别求内参和外参,直接通过二维平面转换求出对应的单应性矩阵H,然后需要的高度Z再单独通过深度相机得到,所以用了单应性来标定,过程中采集了48个角点,最后的误差x轴在3厘米左右,y轴误差在毫米级,暂时能用,先用着,再去研究其他的方法。
二、标定原理
在计算机视觉中,平面的单应性被定义为一个平面到另外一个平面的投影映射。因此一个二维平面上的点映射到摄像机成像仪上的映射就是平面单应性的例子。如果点Q到成像仪上的点q的映射使用齐次坐标,这种映射可以用矩阵相乘的方式表示。若有一下定义:
则可以将单应性简单的表示为:
这里引入参数s,它是任意尺度的比例(目的是使得单应性定义到该尺度比例)。通常根据习惯放在H的外面。
H有两部分组成:用于定位观察的物体平面的物理变换和使用摄像机内参数矩阵的投影。
物理变换部分是与观测到的图像平面相关的部分旋转R和部分平移t的影响之和,表示如下
这里R为3*3大小的矩阵,t表示一个一个3维的列矢量。
摄像机内参数矩阵用M表示,那么我们重写单应性如下:
我们知道单应性研究的是一个平面上到另外一个平面的映射,那么上述公式中的Q,就可以简化为平面坐标中的Q’,即我们使Z=0。即物体平面上的点我们用 x,y表示,相机平面上的点,我们也是用二维点表示。我们去掉了Z方向的坐标,那么相对于旋转矩阵R,R可以分解为R=[r1 r2 r3],那么r3也就不要了,参考下面的推导:
其中H为:
是一个3×3大小的矩阵.
故最终的单应性矩阵可表示如下:
s是相机到物体表面的长度分之一,只是一个比例,我们不需要知道,我的理解就是,我们求出来的是一个H’,而且H’=sH(如果我理解错了,希望指正)。
所以q=H’Q,我们的函数就是求解H’。
Q是物体平面的坐标,q是像素图像的坐标,前者单位我用的是mm,后者是pixel。
我们只需要得到四组对应的点,就可以解的H’,那么为什么是四组,推导如下:
假设p(xi’,yi’),Q(xi,yi),有下面公式:
最后我们可以得到如下系数矩阵A:
解其次线性方程组可得Ax=0可得:
因为是齐次坐标系得到的方程组,H’九个未知数中的一个可以用其他的8个未知数来表示,所以最后我们只需要求解8个未知数(如果理解有错请指正),有上图方程组可以得到一组点可以确定两个方程,所以我们至少需要四组点。
三、findHomography 函数与 getPerspectiveTransform函数的区别
1、两者联系
都是Opencv中的函数,都用于计算单应矩阵,即解一个线性方程组。由于单应矩阵有8个未知数(3*3,其中第9个数为1),所以至少需要4个点(每个点-x,y,提供2个约束方程)。
2、两者区别
(1)计算方法不同
通过跟踪源码,发现getPerspectiveTransform用的是SVD分解,findHomography看不出是用什么方法(没注释,一堆等式)。但两者计算结果是一样的。
(2)输入参数不同
getPerspectiveTransform只会拿前4个点去计算,findHomography则会拿一堆点(>=4)去计算(其是不断从一堆点中重复拿出4个点去计算出一个结果,再采用一些优化算法RANSAC/LMEDS去筛选出最优解)。
四、代码实现
1、棋盘格下载地址
(1)输入的48组点,来自黑白棋盘的角点检测,真实的场景桌面坐标以第一个角点为(0,0),依次往下计算。
棋盘下载地址
说明:大小为8x6,可以用A4纸打印出来,square边长为24.5mm,即0.0245m。
2、代码(c++)
#include <opencv2/opencv.hpp>
#include <iostream>
#include <iostream*>
#include <****fstream****>
#include <****vector****>using namespace cv;
using namespace std;int main()
{//图像尺寸cv::Size imageSize;//标定板上每行每列的角点数cv::Size boardSize = cv::Size(8, 6);//缓存图像上检测到的角点std::vector<Point2f> imagePointsBuf;std::vector<Point2f> imagePointsSeq;//读入第一张图片并获取图宽高信息Mat imageInput = cv::imread("qipan/qipan_1.png");cv::imshow("imageInput", imageInput);imageSize.width = imageInput.cols;imageSize.height = imageInput.rows;std::cout << "imageSize.width = " << imageSize.width << std::endl;std::cout << "imageSize.height = " << imageSize.height << std::endl;//提取图片的角点if (cv::findChessboardCorners(imageInput, boardSize, imagePointsBuf) == 0){//找不到角点std::cout << "Can not find chessboard corners!" << std::endl;exit(1000);}else{//输出48个角点//std::cout << "imagePointsBuf = " << imagePointsBuf << std::endl;//int c = imagePointsBuf.size();//std::cout << c << std::endl;//转换为灰度图片Mat viewGray;cv::cvtColor(imageInput, viewGray, cv::COLOR_BGR2GRAY);//亚像素精确化 对粗提取的角点进行精确化cv::find4QuadCornerSubpix(viewGray, imagePointsBuf, cv::Size(5, 5));//保存亚像素点//imagePointsSeq.push_back(imagePointsBuf);std::cout << "二维像素图像点 :" << imagePointsBuf << std::endl;//在图像上显示角点位置//cv::drawChessboardCorners(viewGray, boardSize, imagePointsBuf, true);//显示图片//cv::imshow("Camera Calibration", viewGray);//cv::imwrite("test.jpg", viewGray);//等待0.5s//waitKey(500);}//计算每张图片上的角点数 54int cornerNum = boardSize.width * boardSize.height;std::vector<cv::Point2f> scene_PointSet;//行数for (int i = 0; i < 8; i++){//列数for (int j = 0; j < 6; j++){cv::Point2f realPoint;//假设标定板放在世界坐标系中z=0的平面上。realPoint.x = i*24.5;realPoint.y = j*24.5;scene_PointSet.push_back(realPoint);}}std::cout << "桌面坐标点 :" << scene_PointSet << std::endl;//std::cout << "DAXIAO :" << scene_PointSet.size() << std::endl;Mat h = findHomography(scene_PointSet, imagePointsBuf);//Mat h = findHomography(imagePointsBuf, scene_PointSet);//Mat warpPerspective_dst;//warpPerspective(imageInput, warpPerspective_dst, h, imageInput.size());//imshow("warpPerspective_dst", warpPerspective_dst);//cv::Mat L = cv::Mat(48, 1, CV_64F, Scalar::all(1));//Mat N;//hconcat(scene_PointSet, L, N);//std::cout << "l :" <<N << std::endl;//Mat two_zhuanhuan = h*three_PointSet;std::cout << "单应性矩阵 :" << h << std::endl;cv::waitKey(0);
}
3、结果
单应性矩阵 H:
[-0.3867898753811677, -0.1024058969404837, 350.2522938027052; 0.04115322376139761, 0.003417522906883271, 181.9737528555213; -0.000207711216987611, -0.0001663297582563403, 1]
相机标定-opencv单应性矩阵实现平面坐标标定(kinect v1)相关推荐
- 相机标定 和 单应性矩阵H
参考链接: https://blog.csdn.net/yonger_/article/details/55194602 单应性矩阵优化(物体识别+跟踪)(AR方向) 基于fastcv识别分析,MAT ...
- 透视变换 单应性矩阵怎么求 matlab,单应性(homography)变换的推导
矩阵的一个重要作用是将空间中的点变换到另一个空间中.这个作用在国内的<线性代数>教学中基本没有介绍.要能形像地理解这一作用,比较直观的方法就是图像变换,图像变换的方法很多,单应性变换是其中 ...
- 基于匹配点集对单应性矩阵进行估计
基于匹配点集对单应性矩阵进行估计 2020/4/28 FesianXu 前言 在立体视觉中,对单应性矩阵进行估计是一个很重要的任务,我们在之前的博文[1,2,3]中的讨论中都或多或少地涉及到了单应性矩 ...
- akaze特征匹配怎么去掉不合适的点_单应性矩阵应用基于特征的图像拼接
点击上方蓝字关注我们 微信公众号:OpenCV学堂 关注获取更多计算机视觉与深度学习知识 前言 前面写了一篇关于单应性矩阵的相关文章,结尾说到基于特征的图像拼接跟对象检测中单应性矩阵应用场景.得到很多 ...
- 单应性矩阵在标定中的应用
1.单应性矩阵是什么? 言简意赅定义:定义在两个不同视角中对同一平面范围内的特征点的射影变换(projective transformation)即: x1 = H*x2 //x1.x2为匹配点 上图 ...
- 单应性矩阵H和相机姿态参数R和T关系
单应性矩阵H和相机姿态参数R和T关系 H H H 矩阵包含什么内容? 相似变换 H s H_s Hs : 旋转.平移.缩放 仿射变换 H a H_a Ha 射影变换 H p H_p Hp H H ...
- opencv求两张图像光流_OpenCV单应性矩阵发现参数估算方法详解
点击上方蓝字关注我们 微信公众号:OpenCV学堂 关注获取更多计算机视觉与深度学习知识 单应性矩阵计算函数与应用 OpenCV在通过特征描述子完成描述子匹配之后,会得到一些关键点对,我们会把这些关键 ...
- OpenCV学习:仿射变换+投射变换+单应性矩阵
OpenCV学习:仿射变换+投射变换+单应性矩阵 estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切 ...
- Homography matrix(单应性矩阵)在广告投放中的实践
原文首发于微信公众号「3D视觉工坊」. 前言 由于近期在研究相机与投影仪的标定程序时,需要将结构光图片与灰点相机拍摄得到的图片中,找出角点之间的对应性,使用了如下一条代码: Mat HomoMatri ...
最新文章
- 我热爱计算机作文500字,电脑吸引了我
- 【Python】核酸结果统计难?复旦博士生的操作火了......
- HTML页面显示缩略所有空格为一格的方法
- Java(enum)枚举用法详解
- 科创板5只股发行市盈率高达40、50倍,会有什么风险?
- 怎样让jquery mobile 的footer/header 固定?
- mysql五日均线代码_通达信均线源码,5日通达信均线公式源码
- 【SVPWM】SVPWM算法推导及其Simulink仿真(二)
- windows datacenter 2012 R2 密钥
- 盘点面试中常见的智力题
- JumpServer页面访问502、504问题记录
- 三星研究院:发现腾讯的“阿喀琉斯之踵”,互联网营销
- 火狐使用谷歌搜索_使Firefox快速搜索使用Google的Beta搜索键
- JSAPI微信支付java
- Pythonic写法
- 高校wifi认证登录
- php+mysql(5.1)+apache+centos 编译安装
- 解决软件提示错误0xc000007b
- PySide2学习总结(十二)打开文件对话框--FileDialog
- UML类图示例一张:公司结构
热门文章
- 你该选择哪种编程语言来开发App呢?
- Flink学习-DataStream-HDFSConnector(StreamingFileSink)
- spring cloud 的getway路由配置(网关配置)
- LabVIEW图形化TensoRT工具包的安装下载分享
- 逻辑回归中的梯度下降法
- 爬取微信公众号发布的所有文章(包括阅读数,在看数,点赞数)
- ps—选择连续的多个图层、同时操作多个图层、选择所有图层与取消选择图层、锁定图层、锁定透明像素、锁定图像像素、锁定位置、锁定全部
- 平均年薪 50 万的无人驾驶工程师,需要掌握这 5 大关键技术
- 数据结构排序-7-3 点赞狂魔 (25 分)
- linux修改主机名命令