OpenCv,分解并重新组合投影矩阵

时间:2018-05-23 10:21:58

标签: opencv

我有一个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

我在哪里错了?

1 个答案:

答案 0 :(得分:0)

您需要将Td转换为4通道1x1矩阵。

cv::convertPointsFromHomogeneous(Td.reshape(4), T);

然后,您可能需要将T转换为1通道3x1矩阵:

T = T.reshape(1).t();

请注意,T是相机在世界范围内的位置。 您可能需要使用-Rd*T作为翻译。