基于opencv的SVD分解求解变换矩阵

这篇具有很好参考价值的文章主要介绍了基于opencv的SVD分解求解变换矩阵。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于opencv的SVD分解求解变换矩阵

一、坐标转换关系

在机器视觉领域,坐标系之间的转换是必不可少的。空间坐标转换的实质是用公共点的两套坐标去推导出两个坐标系之间的转换关系:R(旋转矩阵)和T(平移向量)。

opencv svdecomp,三维测量,opencv,计算机视觉
opencv svdecomp,三维测量,opencv,计算机视觉

二、算法原理

其实点云的配准过程就是求解旋转矩阵R和平移向量T,这里记目标函数为:
opencv svdecomp,三维测量,opencv,计算机视觉
式中,n是匹配点个数,假设其最小二乘解为R’和T’,那么opencv svdecomp,三维测量,opencv,计算机视觉

和Q的质心相同(最小二乘法的原理决定的),其中:
opencv svdecomp,三维测量,opencv,计算机视觉
而P的质心为:

opencv svdecomp,三维测量,opencv,计算机视觉
接着使:
opencv svdecomp,三维测量,opencv,计算机视觉
这时目标函数可以改写为:
opencv svdecomp,三维测量,opencv,计算机视觉
分解:
opencv svdecomp,三维测量,opencv,计算机视觉
求导,则有:
opencv svdecomp,三维测量,opencv,计算机视觉
上式中H为三阶方阵:
opencv svdecomp,三维测量,opencv,计算机视觉
用SVD分解H矩阵有:
opencv svdecomp,三维测量,opencv,计算机视觉
令X=VUT,则有:

opencv svdecomp,三维测量,opencv,计算机视觉
由此可见XH为对称正定矩阵,所以对任意的三阶正交方阵B有tr(XH)≥tr(BXH),则对于所有的三阶正交方阵中,只有当X的行列式接近于1或者等于1时,则旋转矩阵R=X。那么平移矩阵为:
opencv svdecomp,三维测量,opencv,计算机视觉文章来源地址https://www.toymoban.com/news/detail-670643.html

三、代码实现

//SVD计算坐标转换,输入为公共点在两个坐标系的坐标,输出为旋转矩阵和平移向量
void GetRigidTrans3D(cv::Point3f* srcPoints, cv::Point3f* dstPoints, int pointsNum, TRigidTrans3D& transform)
{
	double srcSumX = 0.0f;
	double srcSumY = 0.0f;	
	double srcSumZ = 0.0f;	
	double dstSumX = 0.0f;	
	double dstSumY = 0.0f;	
	double dstSumZ = 0.0f;	
	//计算质心	
	for (int i = 0; i < pointsNum; ++i)	
	{		
		srcSumX += srcPoints[i].x;		
		srcSumY += srcPoints[i].y;		
		srcSumZ += srcPoints[i].z;		
		dstSumX += dstPoints[i].x;		
		dstSumY += dstPoints[i].y;		
		dstSumZ += dstPoints[i].z;			
	}	
	cv::Point3f centerSrc, centerDst;	
	centerSrc.x = float(srcSumX / pointsNum);	
	centerSrc.y = float(srcSumY / pointsNum);	
	centerSrc.z = float(srcSumZ / pointsNum);	
	centerDst.x = float(dstSumX / pointsNum);	
	centerDst.y = float(dstSumY / pointsNum);	
	centerDst.z = float(dstSumZ / pointsNum);	
	cv::Mat srcMat(3, pointsNum, CV_32FC1);	
	cv::Mat dstMat(3, pointsNum, CV_32FC1);	
	float* srcDat = (float*)(srcMat.data);	
	float* dstDat = (float*)(dstMat.data);	
	for (int i = 0; i < pointsNum; ++i)	
	{	
		srcDat[i] = srcPoints[i].x - centerSrc.x;
		srcDat[pointsNum + i] = srcPoints[i].y - centerSrc.y;		
		srcDat[pointsNum * 2 + i] = srcPoints[i].z - centerSrc.z;
		dstDat[i] = dstPoints[i].x - centerDst.x;		
		dstDat[pointsNum + i] = dstPoints[i].y - centerDst.y;		
		dstDat[pointsNum * 2 + i] = dstPoints[i].z - centerDst.z;
	}
	//SVD分解	
	cv::Mat matS = srcMat * dstMat.t();	
	cv::Mat matU, matW, matV;	
	cv::SVDecomp(matS, matW, matU, matV);	
	cv::Mat matTemp = matU * matV;	
	double det = cv::determinant(matTemp);	
	float datM[] = { 1, 0, 0, 0, 1, 0, 0, 0, det };	
	cv::Mat matM(3, 3, CV_64FC1, datM);	
	cv::Mat matR = matV.t() * matM * matU.t();	
	transform.matR[0] = matR.at<float>(0, 0);	
	transform.matR[1] = matR.at<float>(0, 1);	
	transform.matR[2] = matR.at<float>(0, 2);	
	transform.matR[3] = matR.at<float>(1, 0);	
	transform.matR[4] = matR.at<float>(1, 1);	
	transform.matR[5] = matR.at<float>(1, 2);	
	transform.matR[6] = matR.at<float>(2, 0);	
	transform.matR[7] = matR.at<float>(2, 1);	
	transform.matR[8] = matR.at<float>(2, 2); 	
	double* datR = (double*)(transform.matR);	
	transform.X = centerDst.x - (centerSrc.x * datR[0] + centerSrc.y * datR[1] + centerSrc.z * datR[2]);	
	transform.Y = centerDst.y - (centerSrc.x * datR[3] + centerSrc.y * datR[4] + centerSrc.z * datR[5]);	
	transform.Z = centerDst.z - (centerSrc.x * datR[6] + centerSrc.y * datR[7] + centerSrc.z * datR[8]); 
}

到了这里,关于基于opencv的SVD分解求解变换矩阵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Matlab中求解线性方程组——高斯消元法、LU分解法、QR分解法、SVD分解法、迭代法等

    MATLAB迭代的三种方式以及相关案例举例 MATLAB矩阵的分解函数与案例举例 MATLAB当中线性方程组、不定方程组、奇异方程组、超定方程组的介绍 MATLAB语句实现方阵性质的验证 MATLAB绘图函数的相关介绍——海底测量、二维与三维图形绘制 MATLAB求函数极限的简单介绍 文章目录 前言

    2024年02月08日
    浏览(66)
  • 3D点云处理:用SVD分解法和最小二乘法拟合平面点云,求解平面方程

    本文主要介如何用SVD分解法和最小二乘法拟合平面点云,包含原理推导和代码 将空间中的离散点拟合为一个平面,就是使离散点到某个平面距离和最小的问题,可以将求解过程看作最优化的过程。 一个先验知识为拟合平面一定经过离散点的质心(离散点坐标的平均值)。平

    2024年02月03日
    浏览(177)
  • Python实现矩阵奇异值分解(SVD)

    Python实现矩阵奇异值分解(SVD) 矩阵奇异值分解(Singular Value Decomposition, SVD)是一种重要的矩阵分解方法,可以将一个矩阵分解成三个矩阵的乘积,即 A = U Σ V T A=USigma V^{T} A = U Σ

    2024年02月10日
    浏览(45)
  • 矩阵篇(五)-- 特征值分解(EVD)和奇异值分解(SVD)

            设 A n × n A_{n times n} A n × n ​ 有 n n n 个线性无关的特征向量 x 1 , … , x n boldsymbol{x}_{1}, ldots, boldsymbol{x}_{n} x 1 ​ , … , x n ​ ,对应特征值分别为 λ 1 , … , λ n lambda_{1}, ldots, lambda_{n} λ 1 ​ , … , λ n ​ A [ x 1 ⋯ x n ] = [ λ 1 x 1 ⋯ λ n x n ] Aleft[begin{array}{lll

    2024年02月08日
    浏览(52)
  • 矩阵:采用奇异值分解(SVD)对n个点进行平面拟合

    奇异值分解(Singular Value Decomposition, SVD),是线性代数中一种重要的矩阵分解,在信号处理、统计学等领域有重要应用。奇异值分解在某些方面与对称矩阵或厄米矩阵基于特征向量的对角化类似。对称矩阵特征向量分解的基础是谱分析,而奇异值分解则是谱分析理论在任意矩

    2023年04月08日
    浏览(39)
  • 【线性代数/机器学习】矩阵的奇异值与奇异值分解(SVD)

    我们知道,对于一个 n × n ntimes n n × n 的矩阵 A A A ,如果 A A A 有 n n n 个线性无关的特征向量,则 A A A 可以相似对角化,即存在可逆矩阵 P P P 使得 A = P Λ P − 1 A=PLambda P^{-1} A = P Λ P − 1 ,其中 Λ Lambda Λ 是 A A A 的特征值组成的对角阵。 P P P 的列实际上就是 A A A 的特征向

    2024年02月10日
    浏览(41)
  • 时序分解 | MATLAB实现基于SVD奇异值分解的信号分解分量可视化

    效果一览 基本介绍 SVD分解重构算法,MATLAB程序,奇异值分解 (Singular Value Decomposition)是一种常见的矩阵分解方法,用于将矩阵分解成三个矩阵的乘积。在信号处理中,SVD 可以用于特征提取、信号降维、图像压缩等方面。SVD 的一个重要应用是主成分分析 (PCA),可以用于提取数

    2024年02月11日
    浏览(51)
  • 求解仿射变换矩阵

    仿射变换是图形学中经常用到的方法,通常但是仿射变换的系数是未知的,需要找到变换前后的三对对应点进行求解。 参考文献 矩阵最小二乘法求解仿射变换矩阵

    2024年02月08日
    浏览(46)
  • 第三章,矩阵,07-用初等变换求逆矩阵、矩阵的LU分解

    玩转线性代数(19)初等矩阵与初等变换的相关应用的笔记,例见原文 已知: A r ∼ F A^r sim F A r ∼ F ,求可逆阵 P P P ,使 P A = F PA = F P A = F ( F F F 为 A A A 的行最简形) 方法:利用初等行变换,将矩阵A左边所乘初等矩阵相乘,从而得到可逆矩阵P. 步骤: (1)对矩阵A进行l次初等

    2024年02月13日
    浏览(45)
  • 三维坐标变换及其矩阵

    三维坐标变换是将三维空间中的点从一个坐标系映射到另一个坐标系的数学操作。这些变换通常包括平移、旋转、缩放和投影等基本操作。以下是一些常见的三维坐标变换以及它们的变换矩阵表示方式: 1. **平移变换(Translation)**:    三维平移变换的矩阵表示为:      

    2024年02月02日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包