c++ OpenCV CVCalibrateCamera2 导致多个错误

Posted

技术标签:

【中文标题】c++ OpenCV CVCalibrateCamera2 导致多个错误【英文标题】:c++ OpenCV CVCalibrateCamera2 is causing multiple errors 【发布时间】:2010-06-11 21:55:53 【问题描述】:

我正在使用 OpenCV 在 C++ 中制作一个简单的校准程序。一切都很顺利,直到我真正尝试调用 CVCalibrateCamera2。此时,我遇到了几个错误之一:

如果我使用的图像数量等于 4(这是从每个图像中绘制的点数:

OpenCV 错误:未知函数中输入参数的大小不匹配(两个矩阵必须具有相同的点数),文件......\src\cv\cvfundam.cpp,第 870 行

如果图像数量低于 20:

OpenCV 错误:未知函数中的参数错误(矩阵元素的总数不能被新的行数整除),文件......\src\cxcore\cxarray.cpp,第 2749 行

否则,如果图片数量为20或以上:

OpenCV Error: Unsupported format or combination of formats (Invalid matrix type) in unknown function, file ......\src\cxcore\cxarray.cpp, line 117

我已经多次检查了 CVCalibrateCamera2 的参数,并且我确信它们相对于彼此具有正确的尺寸。程序似乎在某个地方试图根据图像数量重塑矩阵,但我不知道在哪里或为什么。有任何想法吗?我正在使用 Eclipse Galileo、MINGW 5.1.6 和 OpenCV 2.1。

【问题讨论】:

您能否发布调用 cvCalibrateCamera2 的代码以及生成传递给它的对象点/图像点的代码?这可能有助于缩小问题范围。 【参考方案1】:

我对此不是 100% 确定,但我认为您的对象点不能共线。在您的代码中,您有

const float points [] [2] = 0, 0, 1, 0, 2, 0, 3, 0;

这些点都在同一条线上(x 轴)。我认为对象点必须为 cvCalibrateCamera2 定义一个平面才能工作。这可能解释了您所看到的错误。

据我所知,OpenCV 校准例程主要设计用于棋盘图案(或其他一些平面对象点集),我不知道相同的算法是否适用于您的情况。

【讨论】:

【参考方案2】:

更新:

这是调用CVCalibrateCamera2()的代码:

void calibrate(CvMat * object_points, CvMat * image_points, CvMat * intrinsicsMatrix, CvMat * distortionVector)
    const int point_count = object_points->rows;
    const int image_count = image_points->rows / point_count;
    CvMat * const full_object_points = cvCreateMat(image_count * point_count, 3, CV_32FC1);
    CvMat * const point_counts = cvCreateMat(image_count, 1, CV_32SC1);
    for (int i = 0; i < image_count; i++)
        CV_MAT_ELEM(*point_counts, float, i, 0) = point_count;
        for (int j = 0; j < point_count; j++)
            for (int k = 0; k < 3; k++)
                CV_MAT_ELEM(*full_object_points, float, i * point_count + j, k) = CV_MAT_ELEM(*object_points, float, j, k);
            
        

cvCalibrateCamera2(full_object_points, image_points, point_counts, cvSize(1, 1), intrinsicsMatrix, distortionVector, NULL, NULL, 0);

这是收集点值并将它们传递给上述函数的部分:

int main()
    const float points [] [2] = 0, 0, 1, 0, 2, 0, 3, 0;

    const int image_count = 5;
    const int point_count = sizeof (points) / sizeof(points[1]);

    CvMat * const object_points = cvCreateMat(point_count, 3, CV_32FC1);
    for (int i = 0; i < point_count; i++)
        CV_MAT_ELEM(*object_points, float, i, 0) = points[i][0];
        CV_MAT_ELEM(*object_points, float, i, 1) = points[i][1];
        CV_MAT_ELEM(*object_points, float, i, 2) = 0;
    

    CvMat * const image_points = cvCreateMat(image_count * point_count, 2, CV_32FC1);
    collectPoints(setup, image_count, point_count, image_points); // See below about this

    CvMat * const intrinsicsMatrix = cvCreateMat(3, 3, CV_32FC1);

    CvMat * const distortionVector = cvCreateMat(5, 1, CV_32FC1);

    calibrate(object_points, image_points, intrinsicsMatrix, distortionVector);

在上面的代码中,collectPoints() 是一个使用第三方库(gl.tter 的 WiiYourself wiimote 库,如果重要的话)的函数。代码如下,但重要的是返回的点的值范围是 -.5 到 .5。

void collectPoints(wiimote_setup & setup, const int image_count, const int point_count, CvMat * const image_points)
    image_points->rows = image_count * point_count;
    image_points->cols = 2;

    bool A_pressed = false;
    for (int i = 0; i < image_count; i++)
        while (true)
            setup.remote.RefreshState();
            if (setup.remote.Button.A())
                if (!A_pressed)
                    for (int j = 0; j < point_count; j++)
                        wiimote_state::ir::dot & dot = setup.remote.IR.Dot[j];
                        CV_MAT_ELEM(*image_points, float, i * point_count + j, 0) = .5 - dot.X;
                        CV_MAT_ELEM(*image_points, float, i * point_count + j, 1) = .5 - dot.Y;
                        cout << dot.X <<", " << dot.Y << "\n";
                    
                    cout << "\n";
                    cout.flush();
                    A_pressed = true;
                    break;
                
             else
                A_pressed = false;
            
        
    

【讨论】:

以上是关于c++ OpenCV CVCalibrateCamera2 导致多个错误的主要内容,如果未能解决你的问题,请参考以下文章

图像轮廓检测错误:OpenCV、C++

带有 C++ 的 OpenCV 无法编译

OpenCV(C++):如何显示 yuv 文件?

Borland C++ 2009 中的 OpenCV

c++中如何调用opencv库

OpenCV 3.0 和 c++ (windows)