Opencv 分解投影矩阵给出了意外的结果
我有以下投影矩阵Opencv 分解投影矩阵给出了意外的结果,opencv,Opencv,我有以下投影矩阵p: -375 0 2000 262500 -375 2000 0 262500 -1 0 0 700 该投影矩阵以px(1px等于0.5mm)在探测器上以mm为单位投影3D点,并根据关系p=K[R | t](其中R是旋转矩阵,t是平移向量)从内在矩阵K[R | t]构建 2000 0 375 0 0 1 0 K = 0 2000 375
p
:
-375 0 2000 262500
-375 2000 0 262500
-1 0 0 700
该投影矩阵以px(1px等于0.5mm)在探测器上以mm为单位投影3D点,并根据关系p=K[R | t]
(其中R
是旋转矩阵,t
是平移向量)从内在矩阵K[R | t]
构建
2000 0 375 0 0 1 0
K = 0 2000 375 R = 0 1 0 t = 0
0 0 1 -1 0 0 700
出于某些原因,我需要将p
分解回这些矩阵。当我使用分解投影矩阵时,我将其作为旋转矩阵:
0 0 0
0 0 0
-1 0 0
在我看来,它不像旋转矩阵
此外,当我从开放CV分解中构建投影矩阵时,我得到以下矩阵:
-375 0 0 262500
-375 0 0 262500
-1 0 0 700
看起来很相似,但不一样
我想知道我是做错了什么,还是运气不好,这是这个函数失败的罕见案例之一
请注意,我自己进行了分解,得到了一致的结果,但我更愿意尽可能多地使用开放CV函数。问题似乎在于
分解投影矩阵所使用的RQ分解。
即使矩阵P
的第一个平方是非奇异的,RQDecomp3x3
函数给出了不正确的结果:
0 0 375 0 0 0
R = 0 0 375 Q = 0 0 0
0 0 1 -1 0 0
因此,一种解决方法是使用基于以下内容的自制函数(这里是用Python编写的):
我使用反单位矩阵Q
来构建非传统的Cholesky分解U*
,其中U
是上三角。
这种方法与Peter Sturm的方法略有不同,因为我们使用的是关系P=K[R | t]
,而在Peter Sturm的讲座中使用的是关系P=K[R |-Rt]
2000 0 375 0 0 1 0
K = 0 2000 375 R = 0 1 0 t = 0
0 0 1 -1 0 0 700
一个只使用开放式CV的C++实现更为棘手,因为它们没有真正暴露Cholesky分解的函数:
void chol(cv::Mat const& S, cv::Mat& L)
{
L = cv::Mat::zeros(S.rows, S.rows, cv::DataType<double>::type);
for (int i = 0; i < S.rows; ++i) {
for (int j = 0; j <= i ; ++j) {
double sum = 0;
for (int k = 0; k < j; ++k)
sum += L.at<double>(i,k) * L.at<double>(j,k);
L.at<double>(i,j) = (i == j) ? sqrt(S.at<double>(i,i) - sum) : (S.at<double>(i,j) - sum) / L.at<double>(j,j);
}
}
}
void decomposeP(cv::Mat const& P, cv::Mat& K, cv::Mat& R, cv::Mat& t)
{
cv::Mat M(3, 3, cv::DataType<double>::type);
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
M.at<double>(i, j) = P.at<double>(i ,j);
cv::Mat Q = cv::Mat::zeros(3, 3, cv::DataType<double>::type);
Q.at<double>(0, 2) = 1.0;
Q.at<double>(1, 1) = 1.0;
Q.at<double>(2, 0) = 1.0;
cv::Mat O = Q * M * M.t() * Q;
cv::Mat C;
chol(O, C);
cv::Mat B = Q * C * Q;
K = B / B.at<double>(2,2);
cv::Mat A = K.inv() * M;
double l = std::pow((1 / cv::determinant(A)), 1/3);
R = l * A;
cv::Mat p(3, 1, cv::DataType<double>::type);
for (int i = 0; i < 3; ++i)
p.at<double>(i, 0) = P.at<double>(i ,3);
t = l * K.inv() * p;
}
void chol(cv::Mat const&S,cv::Mat&L)
{
L=cv::Mat::零(S.rows,S.rows,cv::DataType::type);
对于(int i=0;i 对于(int j=0;j你不是得到了0 fx和fy吗?你是从哪里得到这个投影矩阵的?我编辑了我的问题,以提供关于这个投影矩阵起源的更多信息。你可能想用不同的K,R,t值测试你自己的OpenCV分解实现。这样,你就可以确定它是一个边缘情况还是一个缺陷OpenCV。如果您认为此OpenCV函数中存在错误,您还可以检查源代码并打开一个问题。此外,您应该发布OpenCV的源代码,以检查一切是否正常,以及您的实现是否有帮助。