我有一个opencv计算机视觉应用程序。
我正在尝试分解相机投影矩阵,然后我将调整tvec和rvec,并将其重新组合成新的投影矩阵。
为了让这个运行起来,我首先尝试分解矩阵,然后按原样重建它,然后比较结果。
我从xml加载Matrix:
cv::FileStorage fs("calibStereo.xml", cv::FileStorage::READ);
fs["P1"] >> P1;
然后我用:分解矩阵
cv::Mat Kd(3, 3, cv::DataType<float>::type); // intrinsic parameter matrix
cv::Mat Rd(3, 3, cv::DataType<float>::type); // rotation matrix
cv::Mat Td(4, 1, cv::DataType<float>::type); // translation vector
cv::Mat newP1(4, 3, cv::DataType<float>::type);
cv::decomposeProjectionMatrix(P1, Kd, Rd, Td);
这很好用。
然后我有以下函数(来自cv :: sfm模块)
template<typename T>
void
projectionFromMatrices(const cv::Mat_<T> &K, const cv::Mat_<T> &R, const cv::Mat_<T> &t, cv::Mat_<T> P)
{
hconcat(K*R, K*t, P);
}
void MatrixFunctions::projectionFromKRt(cv::Mat _K, cv::Mat _R, cv::Mat _t, cv::Mat &_P)
{
const cv::Mat K = _K, R = _R, t = _t;
const int depth = K.depth();
CV_Assert((K.cols == 3 && K.rows == 3) && (t.cols == 1 && t.rows == 3) && (K.size() == R.size()));
CV_Assert((depth == CV_32F || depth == CV_64F) && depth == R.depth() && depth == t.depth());
_P.create(3, 4, depth);
cv::Mat P = _P;
// type
if (depth == CV_32F)
{
projectionFromMatrices<float>(K, R, t, P);
}
else
{
projectionFromMatrices<double>(K, R, t, P);
}
}
这需要3x1平移向量,而decomposeProjectionMatrix返回4x1。
所以我补充说:
cv::Mat T(3, 1, cv::DataType<float>::type); // new translation vector
cv::convertPointsFromHomogeneous(Td, T);
MatFunc->projectionFromKRt(Kd, Rd, T, newP1);
这在assertion failed
函数中给了convertPointsFromHomogeneous
。
我在哪里错了?
答案 0 :(得分:0)
您需要将Td
转换为4通道1x1矩阵。
cv::convertPointsFromHomogeneous(Td.reshape(4), T);
然后,您可能需要将T
转换为1通道3x1矩阵:
T = T.reshape(1).t();
请注意,T
是相机在世界范围内的位置。
您可能需要使用-Rd*T
作为翻译。