OpenCV StereoCalibrate возвращает ошибку с высоким среднеквадратичным значением

У меня есть некоторые проблемы при вычислении выпрямления стереопар с помощью OpenCV: StereoCalibrate возвращает ошибку с высоким среднеквадратичным значением, и я получаю плохие пары выпрямления. Я попробовал и мою программу исправления, и стерео_калиб.cpp, поставляемый с opencv. Оба они возвращают одинаковые среднеквадратичные ошибки. Кроме того, я запустил свою программу с образцами стереопар в opencv/sample/cpp и получил правильно исправленные изображения. Итак, я считаю, что проблема в том, как я делаю стереоизображение, возможно ли это?

Я использую стереокамеру Htc Evo 3D (3D-смартфон), снимая шахматную доску. Я попытался изменить количество и набор изображений, используемых в качестве входных данных, но наименьшее среднеквадратичное значение стереокалибровки, которое я получил, было около 1,5, а исправленные изображения совершенно неверны.
Есть ли какой-либо «предлагаемый» способ сделать набор изображений для калибровки? ? Спасибо, Андреа


person beco    schedule 23.05.2014    source источник
comment
ОБНОВЛЕНИЕ: если я изменю размер всех калибровочных изображений перед их обработкой, я могу значительно уменьшить среднеквадратичную ошибку, но исправленные изображения не улучшатся. У меня полностью черная выпрямленная пара!   -  person beco    schedule 23.05.2014


Ответы (4)


Проверьте обнаруженные пары фигур шахматной доски (например, с помощью drawChessboardCorners). В некоторых случаях порядок точек различается на обоих изображениях (см. рисунок; на верхнем изображении паттерн распознается справа налево, на нижнем — слева направо). Если это так, то точки больше не соответствуют друг другу. Это приводит к высокой средней ошибке перепроецирования в stereoCalibrate. При проверке изображений для каждой камеры в отдельности с помощью calibrateCamera среднеквадратичное значение может быть очень низким для внутренних характеристик, поскольку различный порядок в стереоизображениях здесь не имеет значения.

введите здесь описание изображения

Я решил проблему, проверив найденные паттерны шахматной доски и удалив пары изображений, в которых паттерн обнаруживается в другом порядке. В моем случае это улучшило среднеквадратичное значение с 15 (только одна или несколько неправильных пар) до менее 1. В случаях, когда пары повреждаются чаще или при использовании изображений с более высоким разрешением (с большим количеством пикселей), ошибка будет намного выше. догадка.

Другим решением может быть использование шаблонов ArUco и ChArUco, где порядок не должен быть двусмысленным, но я не тестировал этот подход.

person Phann    schedule 16.11.2018
comment
Я согласен с ответом Фанна. Несоответствие обнаруженной последовательности углов в левом и правом изображениях вызвало большие ошибки RMS. Удалив пары изображений, в которых шаблон обнаружен в неправильном порядке, мои проблемы были решены. - person user2975702; 10.05.2019

Ознакомьтесь с руководством по частым ошибкам здесь, чтобы узнать, совершали ли вы какие-либо из этих распространенных ошибок.

http://www.cvlibs.net/software/калибровка/mistakes.php

Кроме того, при калибровке стереокамеры вы можете сначала откалибровать каждую камеру отдельно, а затем откалибровать их как стереопару с учетом их предварительно оцененных матриц камер.

другой альтернативный набор инструментов, а также cvlibs (ссылка выше) находится здесь:

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

ваше здоровье

person QED    schedule 23.05.2014
comment
Спасибо за ссылки, они полезны, даже если не решили проблему - person beco; 03.06.2014
comment
первая ссылка мертва - person A_P; 01.04.2021

Я делаю 9 калибровочных снимков шахматной доски 12x18 углов, запрещаю объективы типа «рыбий глаз» k3=0 и уточняю найденные углы до субпиксельных позиций. Минимально достигаемая погрешность составляет около 0,2 при разрешении 640х480. Я предлагаю искать CornerSubpix(), TermCritiria и флаги для стереокалибровки() в документе opencv. Код выглядит так:

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);
person YuZ    schedule 30.10.2014

Привет, провел еще несколько исследований и нашел этот пост в ответе OpenCV. Телефон, кажется, настраивает внутреннюю матрицу, постоянно меняя фокус, и я не могу сделать хорошую калибровку.

person beco    schedule 03.06.2014