OpenCV错误:未知函数中的错误参数<unknown array =“”type =“”>,文件.. \ .. \ .. \ modules \ core \ src \ matrix.cpp,第697行</unknown>

时间:2013-03-18 01:27:23

标签: opencv

我目前正在尝试纠正立体相机以创建视差图。不幸的是,我无法通过立体声整流步骤,因为我一直收到错误

  

“OpenCV错误:未知函数中的错误参数,文件.. \ .. \ .. \ modules \ core \ src \ matrix.cpp,第697行。”

由于我不是校准摄像机的人,也无法访问用于录制视频的摄像机,因此过程变得复杂。我获得了所有校准参数(内在函数,失真系数,旋转矩阵和平移向量)。正如您所看到的,我已经尝试将这些直接转换为CvMats并以这种方式使用它们,但是当我尝试使用它们时出现错误。

提前致谢。

CvMat li, lm, ri, rm, r, t, Rl, Rr, Pl, Pr;    

double init_li[3][3] = 
    {   {477.984984743, 0, 316.17458671}, 
    {0, 476.861945645, 253.45073026}, 
    {0, 0 ,1}   };
double init_lm[5] = {-0.117798518453, 0.147554949385, -0.0549082041898, 0, 0};
double init_ri[3][3] = 
    {{478.640315323, 0, 299.957994781}, 
    {0, 477.898896505, 251.665771947}, 
    {0, 0, 1}};
double init_rm[5] = {-0.10884732532, 0.12118405303, -0.0322073237741, 0, 0};
double init_r[3][3] = 
    {{0.999973709051976, 0.00129700728791757, -0.00713435189275776},
    {-0.00132096594266573, 0.999993501087837, -0.00335452397041856}, 
    {0.00712995468519435, 0.00336386001267643, 0.99996892361313}};
double init_t[3] = {-0.0830973040641153, -0.00062704210860633, 1.4287643345188e-005};

cvInitMatHeader(&li, 3, 3, CV_64FC1, init_li);
cvInitMatHeader(&lm, 5, 1, CV_64FC1, init_lm);
cvInitMatHeader(&ri, 3, 3, CV_64FC1, init_ri);
cvInitMatHeader(&rm, 5, 1, CV_64FC1, init_rm);
cvInitMatHeader(&r, 3, 3, CV_64FC1, init_r);
cvInitMatHeader(&t, 3, 1, CV_64FC1, init_t);
cvInitMatHeader(&Rl, 3,3, CV_64FC1);
cvInitMatHeader(&Rr, 3,3, CV_64FC1);
cvInitMatHeader(&Pl, 3,4, CV_64FC1);
cvInitMatHeader(&Pr, 3,4, CV_64FC1);

//frame is a cv::MAT holding the first frame of the video.
CvSize imageSize = frame.size();
imageSize.width /= 2;

//IT BREAKS HERE
cvStereoRectify(&li, &ri, &lm, &rm, imageSize, &r, &t, &Rl, &Rr, &Pl, &Pr);

3 个答案:

答案 0 :(得分:0)

我不是OpenCV专家,但我想知道您是否正在初步调整Matrix元素,因此我查看了CvMat* cvInitMatHeader(CvMat* mat, int rows, int cols, int type, void* data=NULL, int step=CV_AUTOSTEP)link)的参考资料

从文档中的示例:

double a[] = { 1, 2, 3, 4,
               5, 6, 7, 8,
               9, 10, 11, 12 };

double b[] = { 1, 5, 9,
               2, 6, 10,
               3, 7, 11,
               4, 8, 12 };

double c[9];
CvMat Ma, Mb, Mc ;

cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);
cvInitMatHeader(&Mb, 4, 3, CV_64FC1, b);
cvInitMatHeader(&Mc, 3, 3, CV_64FC1, c);

现在,OpenCV中的矩阵以行主顺序(reference)存储,所以没有任何错误。

我忍不住注意到文档中的示例仅使用单个数组来初始化它们的矩阵,而使用2d数组。 This other SO question似乎可以证明,您可以在不使用cvInitMatHeader设置步长的情况下实例化数组。

作为参考,步骤参数指的是:

  

步骤 - 可选:已分配数据的完整行宽(以字节为单位)。通过   默认情况下,使用最小可能步骤,假设没有   矩阵的后续行之间的间隙。

为了确保你可以在这里使用2D矩阵,我检查了源函数:

// Initializes CvMat header, allocated by the user
CV_IMPL CvMat*
cvInitMatHeader( CvMat* arr, int rows, int cols,
                 int type, void* data, int step )
{
    if( !arr )
        CV_Error( CV_StsNullPtr, "" );

    if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
        CV_Error( CV_BadNumChannels, "" );

    if( rows < 0 || cols <= 0 )
        CV_Error( CV_StsBadSize, "Non-positive cols or rows" );

    type = CV_MAT_TYPE( type );
    arr->type = type | CV_MAT_MAGIC_VAL;
    arr->rows = rows;
    arr->cols = cols;
    arr->data.ptr = (uchar*)data;
    arr->refcount = 0;
    arr->hdr_refcount = 0;

    int pix_size = CV_ELEM_SIZE(type);
    int min_step = arr->cols*pix_size;

    if( step != CV_AUTOSTEP && step != 0 )
    {
        if( step < min_step )
            CV_Error( CV_BadStep, "" );
        arr->step = step;
    }
    else
    {
        arr->step = min_step;
    }

    arr->type = CV_MAT_MAGIC_VAL | type |
        (arr->rows == 1 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);

    icvCheckHuge( arr );
    return arr;
}

一切似乎都很好,步骤被设置为元素类型的字节数*列数。此时,我非常确定您对此功能的调用没有任何问题。

然后我调查了你设置图像大小的位置:

CvSize imageSize = frame.size();

因为frame是C ++样式矩阵,所以它返回Size,而不是cvSize。所以我想知道兼容性。 This other SO post支持您在混合C和C ++ OpenCV代码时遇到随机问题,因此您应该避免使用它。所以我检查了两种类型是否兼容。

手册states

  

(cv :: Size)可以与旧的OpenCV结构进行转换   CvSize和CvSize2D32f。

所以我不得不排除那些时髦的东西。

那么错误在哪里? 你有我,我不知道。可能是您的代码中的其他内容未在此代码段中显示。也许这些信息可以给你或其他人一个想法。

编辑: 我仍然不确定,但是我找到了使用cvStereoRectify的其他人的example,当他们创建了他们的失真矩阵时,它们是1x5而不是5x1。所以你可以尝试改变

cvInitMatHeader(&lm, 5, 1, CV_64FC1, init_lm);
cvInitMatHeader(&rm, 5, 1, CV_64FC1, init_rm);

cvInitMatHeader(&lm, 1, 5, CV_64FC1, init_lm);
cvInitMatHeader(&rm, 1, 5, CV_64FC1, init_rm);

答案 1 :(得分:0)

好的,所以我想出了答案。问题是我只为Rl,Rr,Pl和Pr初始化了标头,但没有为数据本身分配内存。我能够解决它如下:

double init_Rl[3][3];
double init_Rr[3][3];
double init_Pl[3][4];
double init_Pr[3][4];

cvInitMatHeader(&Rl, 3,3, CV_64FC1, init_Rl);
cvInitMatHeader(&Rr, 3,3, CV_64FC1, init_Rr);
cvInitMatHeader(&Pl, 3,4, CV_64FC1, init_Pl);
cvInitMatHeader(&Pr, 3,4, CV_64FC1, init_Pr);

虽然,我有一个理论,我可能已经能够使用cv :: stereoRectify与cv :: Mats作为参数,这将使生活更容易。我不知道cv :: stereoRectify是否存在,但似乎许多其他c函数的版本都在cv名称空间中。如果很难说,我对OpenCV很新。

答案 2 :(得分:0)

所以,你被c-api咬了?你为什么不背弃它呢?

尽可能使用c ++ api,请不要用旧的(1.0),弃用的api开始学习opencv!

double init_li[9] = 
    {   477.984984743, 0, 316.17458671, 
    0, 476.861945645, 253.45073026, 
    0, 0 ,1  };
double init_lm[5] = {-0.117798518453, 0.147554949385, -0.0549082041898, 0, 0};
double init_ri[9] = 
    {   478.640315323, 0, 299.957994781, 
    0, 477.898896505, 251.665771947, 
    0, 0, 1};
double init_rm[5] = {-0.10884732532, 0.12118405303, -0.0322073237741, 0, 0};
double init_r[9] = 
    {   0.999973709051976, 0.00129700728791757, -0.00713435189275776,
    -0.00132096594266573, 0.999993501087837, -0.00335452397041856, 
    0.00712995468519435, 0.00336386001267643, 0.99996892361313};
double init_t[3] = {-0.0830973040641153, -0.00062704210860633, 1.4287643345188e-005};

cv::Mat li(3, 3, CV_64FC1, init_li);
cv::Mat lm(5, 1, CV_64FC1, init_lm);
cv::Mat ri(3, 3, CV_64FC1, init_ri);
cv::Mat rm(5, 1, CV_64FC1, init_rm);
cv::Mat r, t, Rl, Rr, Pl, Pr; // note: no initialization needed.

//frame is a cv::MAT holding the first frame of the video.
cv::Size imageSize = frame.size();
imageSize.width /= 2;

//IT won't break HERE
cv::stereoRectify(li, ri, lm, rm, imageSize, r, t, Rl, Rr, Pl, Pr);

// no need ever to release or care about anything