【问题标题】:cv::getPerspectiveTransform throws Error after cv::eigen2cvcv::getPerspectiveTransform 在 cv::eigen2cv 之后抛出错误
【发布时间】:2022-07-14 20:47:09
【问题描述】:

我的代码

cv::Mat
    getPerspectiveTransform(Eigen::MatrixXd quadrangle, Eigen::MatrixXd warpedQuadrangle) {
        cv::Mat transMat;
        cv::Mat quad(4,2,CV_32FC1);
        cv::Mat warpedQuad(4,2,CV_32FC1);
        cv::eigen2cv(quadrangle,quad);
        cv::eigen2cv(warpedQuadrangle,warpedQuad);
        std::cout << \"[        ] quadrangle in cv::Mat \" << quad << std::endl;
        transMat = cv::getPerspectiveTransform(quad,warpedQuad);
        return transMat;
    }

错误

C++ exception with description \"OpenCV(4.6.0) /home/ci/opencv/modules/imgproc/src/imgwarp.cpp:3392: error: (-215:Assertion failed) src.checkVector(2, CV_32F) == 4 && dst.checkVector(2, CV_32F) == 4 in function \'getPerspectiveTransform\'

疑似问题eigen2cv 正在将我的 CV_32FC1 转换为 CV_64F。 getPerspectiveTransform 期望 CV32F 作为其输入。

理想的解决方案应该是什么?

标签: c++ opencv eigen


【解决方案1】:

eigen2cv 根据输入矩阵的类型改变输出矩阵的布局,从它的source 可以看出。因此,例如,如果您的 Eigen 矩阵使用 64 位浮点数,则输出 Mat 将具有 CV_64F 深度。在这种情况下,最简单的解决方案是使用Mat::convertTo (documentation) 将输出矩阵转换为CV_32F

Mat quadF, warpedQuadF;
quad.convertTo(quadF, CV_32F);
warpedQuad.convertTo(warpedQuadF, CV_32F);
transMat = cv::getPerspectiveTransform(quadF, warpedQuadF);

由于矩阵非常小,这种转换不太可能是性能问题,但可以通过重写 getPerspectiveTransform 函数的 2 个重载(source1source2)来使用 64 位浮点数来避免它。第二个重载只是委托给第一个,第一个在内部使用double,所以它非常简单:

cv::Mat getPerspectiveTransform64(const Point2d src[], const Point2d dst[], int solveMethod)
{
    CV_INSTRUMENT_REGION();
    Mat M(3, 3, CV_64F), X(8, 1, CV_64F, M.ptr());
    double a[8][8], b[8];
    Mat A(8, 8, CV_64F, a), B(8, 1, CV_64F, b);
    for( int i = 0; i < 4; ++i )
    {
        a[i][0] = a[i+4][3] = src[i].x;
        a[i][1] = a[i+4][4] = src[i].y;
        a[i][2] = a[i+4][5] = 1;
        a[i][3] = a[i][4] = a[i][5] = a[i+4][0] = a[i+4][1] = a[i+4][2] = 0;
        a[i][6] = -src[i].x*dst[i].x;
        a[i][7] = -src[i].y*dst[i].x;
        a[i+4][6] = -src[i].x*dst[i].y;
        a[i+4][7] = -src[i].y*dst[i].y;
        b[i] = dst[i].x;
        b[i+4] = dst[i].y;
    }
    solve(A, B, X, solveMethod);
    M.ptr<double>()[8] = 1.;
    return M;
}

cv::Mat getPerspectiveTransform64(InputArray _src, InputArray _dst, int solveMethod)
{
    Mat src = _src.getMat(), dst = _dst.getMat(); 
    CV_Assert(src.checkVector(2, CV_64F) == 4 && dst.checkVector(2, CV_64F) == 4);
    return getPerspectiveTransform64((const Point2d*)src.data, (const Point2d*)dst.data, solveMethod);
}

现在可以直接使用,无需额外转换:

transMat = getPerspectiveTransform64(quad, warpedQuad); 

【讨论】:

    猜你喜欢
    • 2017-09-22
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2012-10-20
    相关资源
    最近更新 更多