首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenCV stereoCalibrate返回高RMS错误

OpenCV stereoCalibrate返回高RMS错误
EN

Stack Overflow用户
提问于 2014-05-23 18:13:51
回答 4查看 5.3K关注 0票数 1

在使用OpenCV计算立体声对的校正时,我遇到了一些问题: stereoCalibrate返回一个高的均方根误差,并且我得到的校正对很差。我尝试了我的整改程序和opencv提供的stereo_calib.cpp。它们都返回类似的rms错误。另外,我用opencv/ sample /cpp中的样本立体声对运行了我的程序,我得到了正确的校正图像。所以我认为问题出在我拍摄立体照片的方式上,有没有可能?

我使用Htc Evo 3D (一款3D智能手机)的立体相机来拍摄棋盘图案。我试着改变作为输入的图片的数量和设置,但我得到的最小的stereoCalibration均方根在1.5左右,校正后的图像完全错误。

有没有什么“建议”的方法来拍摄一组照片进行校准?谢谢,安德里亚

EN

回答 4

Stack Overflow用户

发布于 2018-11-16 20:35:17

检查检测到的棋盘图案对(例如,使用drawChessboardCorners)。在某些情况下,两个图像中点的顺序不同(参见图;在上图中,模式是从右到左识别的,在下图中是从左到右识别的)。如果是这种情况,那么这些点就不再相互对应。这导致了stereoCalibrate中的高平均重投影误差。当使用calibrateCamera分别检查每个摄像机的图像时,对于本征图像,rms可能同时非常低,因为立体图像中的不同顺序在这里并不重要。

我通过检查发现的棋盘图案并删除以不同顺序检测到图案的图像对解决了这个问题。在我的例子中,这将rms从15 (只有一个或几个错误的配对)提高到不到1。如果配对经常损坏,或者使用更高分辨率的图像(具有更多像素),我想误差会更大。

另一种解决方案是使用ArUco和ChArUco模式,其中顺序不应该是模糊的,但我还没有测试过这种方法。

票数 3
EN

Stack Overflow用户

发布于 2014-05-24 05:36:26

查看这里的常见错误指南,看看你是否犯过这些常见错误中的任何一个。

http://www.cvlibs.net/software/calibration/mistakes.php

此外,在校准立体相机时,您可能希望首先校准每个相机本身,然后根据预先估计的相机矩阵将它们作为立体对进行校准。

另一个替代工具箱,以及cvlibs (上面的链接),在这里:

http://www.vision.caltech.edu/bouguetj/calib_doc/

干杯

票数 1
EN

Stack Overflow用户

发布于 2014-10-30 22:52:32

我拍摄了9张12x18角棋盘的校准照片,禁止鱼眼镜头k3=0,并将找到的角细化到亚像素位置。在分辨率为640x480的情况下,最小实现误差约为0.2。我建议在opencv文档中查找cornerSubpix()、TermCritiria和stereocalibrate()的标志。代码如下所示:

代码语言:javascript
复制
namedWindow( "Webcaml", CV_WINDOW_AUTOSIZE );
namedWindow( "Webcamr", CV_WINDOW_AUTOSIZE );
int successes=0;
int n_boards=9;
while(successes<n_boards)
{
    video_l.read( frame_l );
    video_r.read( frame_r );
    if( framenumber++ % board_dt == 0 && framenumber != 0)
    {
        bool patternfoundl = findChessboardCorners( frame_l, Size( board_w, board_h ), corners_l, CV_CALIB_CB_FILTER_QUADS + CV_CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_FAST_CHECK );
        bool patternfoundr = findChessboardCorners( frame_r, Size( board_w, board_h ), corners_r, CV_CALIB_CB_FILTER_QUADS + CV_CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_FAST_CHECK );
        if(patternfoundl && patternfoundr)
        {
            cvtColor(frame_l,frame_l_grey,CV_RGB2GRAY);
            cvtColor(frame_r,frame_r_grey,CV_RGB2GRAY);
            cornerSubPix(frame_l_grey,corners_l,Size(6,6),Size(-1,-1),TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,50000000000,0.0000000000001));
            cornerSubPix(frame_r_grey,corners_r,Size(6,6),Size(-1,-1),TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,50000000000,0.0000000000001));
        }
        drawChessboardCorners( frame_l, Size( board_w, board_h ), corners_l, patternfoundl );
        drawChessboardCorners( frame_r, Size( board_w, board_h ), corners_r, patternfoundr );
        imshow( "Webcaml", frame_l );
        imshow( "Webcamr", frame_r );
        if( corners_l.size() == (board_w*board_h) && corners_r.size() == (board_w*board_h) )
        {
            cornervector_l.push_back( corners_l );
            cornervector_r.push_back( corners_r );
            point3dvector.push_back( point3d );
            successes++;
            int c = cvWaitKey( 1000 );
        }
    }
    else
    {
        imshow( "Webcaml", frame_l);
        imshow( "Webcamr", frame_r);
    }
    char c = cvWaitKey( 1 );
    if( c == 27 )break;
}
destroyAllWindows();
rms_l = calibrateCamera( point3dvector, cornervector_l, Size( video_r.get( CV_CAP_PROP_FRAME_WIDTH ), video_r.get( CV_CAP_PROP_FRAME_HEIGHT )),
                        intrinsics_l, distortion_l, rvecs_l, tvecs_l, CV_CALIB_FIX_K3 , cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,150000000000000000,DBL_EPSILON ) );
rms_r = calibrateCamera( point3dvector, cornervector_r, Size( video_r.get( CV_CAP_PROP_FRAME_WIDTH ), video_r.get( CV_CAP_PROP_FRAME_HEIGHT )),
                        intrinsics_r, distortion_r, rvecs_r, tvecs_r, CV_CALIB_FIX_K3 , cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,150000000000000000,DBL_EPSILON ) );
cout << "intrinsic_l       = " << endl << format(intrinsics_l,"C"     ) << endl << endl;
cout << "intrinsic_r       = " << endl << format(intrinsics_r,"C"     ) << endl << endl;
cout << "distortion_l        = " << endl << format(distortion_l,"C"     ) << endl << endl;
cout << "distortion_r        = " << endl << format(distortion_r,"C"     ) << endl << endl;
cout << "tvecs_l      = " << endl << format(tvecs_l[0],"C"     ) << endl << endl;
cout << "rvecs_l      = " << endl << format(rvecs_l[0],"C"     ) << endl << endl;
double rms_stereo = stereoCalibrate( point3dvector, cornervector_l, cornervector_r, intrinsics_l, distortion_l, intrinsics_r, distortion_r,
                                    Size( video_r.get( CV_CAP_PROP_FRAME_WIDTH ),video_r.get( CV_CAP_PROP_FRAME_HEIGHT )), R, T, E, F, 
                                    TermCriteria( TermCriteria::COUNT+TermCriteria::EPS, 150000000000000000,DBL_EPSILON ), CV_CALIB_FIX_K3+CV_CALIB_FIX_INTRINSIC);
Rodrigues(R, R);
cout << "R       = " << endl << format(R,"C"     ) << endl << endl;
cout << "T        = " << endl << format(T,"C"     ) << endl << endl;
cout << "E       = " << endl << format(E,"C"     ) << endl << endl;
cout << "F        = " << endl << format(F,"C"     ) << endl << endl;
cout << "RMS Fehler l,r,stereo: " << rms_l << rms_r << rms_stereo << endl;
stereoRectify( intrinsics_l, distortion_l, intrinsics_r, distortion_r, Size( video_r.get( CV_CAP_PROP_FRAME_WIDTH ),video_r.get( CV_CAP_PROP_FRAME_HEIGHT )), R, T,
                rectify_l, rectify_r, projection_l, projection_r, Q);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23826541

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档