我目前正在尝试纠正立体相机以创建视差图。不幸的是,我无法通过立体声整流步骤,因为我一直收到错误
“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);
答案 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