【问题标题】:c++ OpenCV CVCalibrateCamera2 is causing multiple errorsc++ OpenCV CVCalibrateCamera2 导致多个错误
【发布时间】: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 的代码以及生成传递给它的对象点/图像点的代码?这可能有助于缩小问题范围。

标签: c++ eclipse opencv


【解决方案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;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-12
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      相关资源
      最近更新 更多