求平面三角形的{PNP}

时间:2017-03-24 17:12:57

标签: c++ opencv pose-estimation opencv-solvepnp

我有一个非常简单的任务:获得平面三角形的欧拉角。模式看起来像this

所以,算法:

1)从网络摄像头获取图像 - 完成

2)转换为gryascale,filter等 - 完成

3)获得所有连接组件的质量中心,并过滤它们 - 完成。看起来像this。红色圆圈描述三角形顶点的质心。

代码很简单,但现在是:

QMap<int, QVector<double> > massCenters(const cv::Mat& image)
{
    cv::Mat output(IMAGE_WIDTH, IMAGE_HEIGHT, CV_32S);
    cv::connectedComponents(image, output, 8);

    QMap<int, QVector<double> > result;

    for (int y = 0; y < IMAGE_HEIGHT; ++y)
    {
        for (int x = 0; x < IMAGE_WIDTH; ++x)
        {
            int label = output.at<int>(y, x);

            if (label)
            {
                QVector<double> vec = result.value(label, QVector<double>());

                if (vec.isEmpty())
                {
                    vec.resize(3);
                    vec.fill(0);
                }

                vec[0] += x;
                vec[1] += y;
                vec[2] += 1;
                result[label] = vec;
            }
         }
    }

    return result;
}

4)然后我调用solvePNP获得旋转&amp;翻译载体

 cv::solvePnP(m_origin, m_imagePoints, m_cameraMatrix, m_distMatrix, m_rvec, m_tvec);

 //this code is for drawing rvec & tvec on a screen
 std::vector<cv::Point3f> axis;
 vector<cv::Point2f> axis2D;

 axis.push_back(Point3f(0.0f, 0.0f, 0.0f));
 axis.push_back(Point3f(30.0f, 0.0f, 0.0f));
 axis.push_back(Point3f(0.0f, 30.0f, 0.0f));
 axis.push_back(Point3f(0.0f, 0.0f, 30.0f));

 cv::projectPoints(axis, m_rvec, m_tvec, m_cameraMatrix, m_distMatrix, axis2D);

 cv::line(m_orig, axis2D[0], axis2D[1], cv::Scalar(255, 0, 0), 2);
 cv::line(m_orig, axis2D[0], axis2D[2], cv::Scalar(0, 255, 0), 2);
 cv::line(m_orig, axis2D[0], axis2D[3], cv::Scalar(0, 0, 255), 2);

m_origin 被声明为std::vector<cv::Point3f> m_origin;并填充了值(以mm为单位)

m_origin.push_back(cv::Point3f( 0.0f,   51.0f, 0.0f));
m_origin.push_back(cv::Point3f(-56.0f, -26.0f, 0.0f));
m_origin.push_back(cv::Point3f( 56.0f, -26.0f, 0.0f));

m_imagePoints 声明为std::vector<cv::Point2f> m_imagePoints;并包含质量中心的像素坐标(第二个屏幕上的红色圆圈)。

我得到了非常奇怪的结果:从thisthat

我尝试了什么,但它对我没有帮助:

1)在m_cameraMatrix,m_distMatrix,m_rvec,m_tvec

中使用了double和float类型

2)重新排列m_origin中的点

3)使用solvePnPRansac及其输入参数

4)使用pnp方法:迭代和epnp

5)useExtrinsicGuess = true - 它有帮助,但有时解决方案是&#34;卡住&#34;并给出完全错误的值(旋转矢量为千度)

我有几个问题:

1)原点和图像点的顺序是否重要?正如前面提到的那样here,但它是在一年前发生的。

2)我的任务可以用其他方式解决,而不是使用solvePnP吗?

感谢。非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

solvePnPRansac不适合你的情况,因为你不必处理异常值数据。

我的猜测是你观察到的问题来自你选择的模式:

  • 这是3分
  • 并添加三角形的质心

但在我看来,它或多或少类似于只使用3个点,因为你添加的第四个点是三角形的重心,不应该在姿势估计问题中给出任何额外的信息。

关于3点(P3P)的姿势估计问题,最多有四种可能的解决方案,并且可以使用第四点去除模糊度。关于这一点的一些参考:

我的建议是使用4点方形而测试以查看是否观察到同样的问题(P3P标志应该没问题)。如果是,则代码或校准中存在问题。

我认为这篇论文或多或少与这个问题有关:Why is the Danger Cylinder Dangerous in the P3P Problem?。链接变得不可用时的数字:

Danger cylinder