OpenCV StereoSGBM дает очень плохую карту несоответствий

это мой код калибровки:

  void calibrate()
 {
    int numBoards = 10;
    int board_w = 6;
    int board_h = 9;
    Size board_sz = Size(board_w, board_h);
    int board_n = board_w*board_h;
    vector<vector<Point3f> > object_points;
    vector<vector<Point2f> > imagePoints1, imagePoints2;
    vector<Point2f> corners1, corners2;
    vector<Point3f> obj;
    for (int j=0; j<board_n; j++)
    {
        obj.push_back(Point3f(j/board_w, j%board_w, 0.0f));
    }
    Mat img1, img2, gray1, gray2;
    VideoCapture cap1(0);
    VideoCapture cap2(1);
    int success = 0, k = 0;
    bool found1 = false, found2 = false;
    namedWindow("left 1");
    namedWindow("right 1");
    while (success < numBoards)
    {
        cap1 >> img1;
        cap2 >> img2;

        cvtColor(img1, gray1, CV_BGR2GRAY);
        cvtColor(img2, gray2, CV_BGR2GRAY);
        found1 = findChessboardCorners(img1, board_sz, corners1, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
        found2 = findChessboardCorners(img2, board_sz, corners2, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
        if (found1)
        {
            cornerSubPix(gray1, corners1, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
            drawChessboardCorners(gray1, board_sz, corners1, found1);
        }
        if (found2)
        {
            cornerSubPix(gray2, corners2, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
            drawChessboardCorners(gray2, board_sz, corners2, found2);
        }
        imshow("left 1", img1);
        imshow("right 1", img2);
        k = cv::waitKey(2);
        if(found1) cout<<"found 1"<<endl;
        if(found2) cout<<"found 2"<<endl;
        if(!found1 && !found2) cout<<"no"<<endl;

        if ( found1  && found2)
        {
            imagePoints1.push_back(corners1);
            imagePoints2.push_back(corners2);
            object_points.push_back(obj);
            printf ("Corners stored\n");
            success++;
            if (success >= numBoards)
            {
                break;
            }
        }
    }
    destroyAllWindows();
    printf("Starting Calibration\n");
    Mat CM1 = Mat(3, 3, CV_64FC1);
    Mat CM2 = Mat(3, 3, CV_64FC1);
    Mat D1, D2;
    Mat R, T, E, F;
    stereoCalibrate(object_points, imagePoints1, imagePoints2,
    CM1, D1, CM2, D2, img1.size(), R, T, E, F,
    cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, 1e-5),
    CV_CALIB_SAME_FOCAL_LENGTH | CV_CALIB_ZERO_TANGENT_DIST);
    FileStorage fs1("mystereocalib.yml", FileStorage::WRITE);
    fs1 << "CM1" << CM1;
    fs1 << "CM2" << CM2;
    fs1 << "D1" << D1;
    fs1 << "D2" << D2;
    fs1 << "R" << R;
    fs1 << "T" << T;
    fs1 << "E" << E;
    fs1 << "F" << F;
    printf("Done Calibration\n");
    printf("Starting Rectification\n");
    Mat R1, R2, P1, P2, Q;
    stereoRectify(CM1, D1, CM2, D2, img1.size(), R, T, R1, R2, P1, P2, Q);
    fs1 << "R1" << R1;
    fs1 << "R2" << R2;
    fs1 << "P1" << P1;
    fs1 << "P2" << P2;
    fs1 << "Q" << Q;
    printf("Done Rectification\n");
    printf("Applying Undistort\n");
    Mat map1x, map1y, map2x, map2y;
    Mat imgU1, imgU2;
    initUndistortRectifyMap(CM1, D1, R1, P1, img1.size(), CV_32FC1, map1x, map1y);
    initUndistortRectifyMap(CM2, D2, R2, P2, img2.size(), CV_32FC1, map2x, map2y);
    printf("Undistort complete\n");

    cap1.release();
    cap2.release();
    return;
 }

И это мой код карты несоответствия с разными параметрами:

    int main(int argc, char* argv[])
{
    //calibrate();

    Mat img1, img2;

    VideoCapture cap1 = VideoCapture(0);
    VideoCapture cap2 = VideoCapture(1);

    cap1 >> img1;
    cap2 >> img2;

    Mat Q;
    FileStorage fs("mystereocalib.yml", FileStorage::READ);
    fs["Q"] >> Q;

    Mat CM1, CM2, D1, D2, P1, P2, R1, R2;

    fs["CM1"] >> CM1;
    fs["CM2"] >> CM2;
    fs["D1"] >> D1;
    fs["D2"] >> D2;
    fs["P1"] >> P1;
    fs["P2"] >> P2;
    fs["R1"] >> R1;
    fs["R2"] >> R2;

    fs.release();

    Mat map1x, map1y, map2x, map2y;
    Mat imgU1, imgU2;
    initUndistortRectifyMap(CM1, D1, R1, P1, img1.size(), CV_32FC1, map1x, map1y);
    initUndistortRectifyMap(CM2, D2, R2, P2, img2.size(), CV_32FC1, map2x, map2y);


    while(1) 
    {
    cap1 >> img1;
    cap2 >> img2;

    imshow("img1", img1);
    imshow("img2", img2);
    cv::waitKey(1);

    remap(img1, imgU1, map1x, map1y, INTER_LINEAR, BORDER_CONSTANT, Scalar());
    remap(img2, imgU2, map2x, map2y, INTER_LINEAR, BORDER_CONSTANT, Scalar());


    Mat g1,g2, disp, disp8;

    cvtColor(imgU1, g1, CV_BGR2GRAY);
    cvtColor(imgU2, g2, CV_BGR2GRAY);

    /*StereoSGBM sbm;
    sbm.SADWindowSize = 5;
    sbm.numberOfDisparities = 144;
    sbm.preFilterCap = 63;
    sbm.minDisparity = -39;
    sbm.uniquenessRatio = 10;
    sbm.speckleWindowSize = 100;
    sbm.speckleRange = 32;
    sbm.disp12MaxDiff = 2;
    sbm.fullDP = true;
    sbm.P1 = 216;
    sbm.P2 = 864;
    sbm(g1, g2, disp);*/

    int sadSize = 3;
    StereoSGBM sbm;
    sbm.SADWindowSize = sadSize;
    sbm.numberOfDisparities = 128;//144;
    sbm.preFilterCap = 63;
    sbm.minDisparity = 0; //-39;
    sbm.uniquenessRatio = 10;
    sbm.speckleWindowSize = 100;
    sbm.speckleRange = 32;
    sbm.disp12MaxDiff = 1;
    sbm.fullDP = true;
    sbm.P1 = sadSize*sadSize*4;
    sbm.P2 = sadSize*sadSize*32;
    sbm(g1, g2, disp);

    //StereoSGBM sgbm;
    //sgbm.SADWindowSize = 5;
    //sgbm.numberOfDisparities = 192;
    //sgbm.preFilterCap = 4;
    //sgbm.minDisparity = -64;
    //sgbm.uniquenessRatio = 1;
    //sgbm.speckleWindowSize = 150;
    //sgbm.speckleRange = 2;
    //sgbm.disp12MaxDiff = 10;
    //sgbm.fullDP = false;
    //sgbm.P1 = 600;
    //sgbm.P2 = 2400;
    //sgbm(g1, g2, disp);


    //StereoBM sbm;
    //sbm.state->SADWindowSize = 9;
    //sbm.state->numberOfDisparities = 112;
    //sbm.state->preFilterSize = 5;
    //sbm.state->preFilterCap = 61;
    //sbm.state->minDisparity = -39;
    //sbm.state->textureThreshold = 507;
    //sbm.state->uniquenessRatio = 0;
    //sbm.state->speckleWindowSize = 0;
    //sbm.state->speckleRange = 8;
    //sbm.state->disp12MaxDiff = 1;
    //sbm(g1, g2, disp);


    normalize(disp, disp8, 0, 255, CV_MINMAX, CV_8U);
    //disp.convertTo(disp8, CV_8U);

    imshow("disp8", disp8);


    }

    waitKey(0);

    return 0;
}

Я новичок в OpenCV и обработке изображений, что я делаю неправильно?


person Aram Gevorgyan    schedule 08.02.2015    source источник
comment
StereoCalibrate() возвращает значение ошибки, пожалуйста, проверьте, если ваша калибровка уже была плохой.   -  person berak    schedule 08.02.2015
comment
@berak Хорошо, спасибо, я проверю. Может быть, numBoards=10 недостаточно для хорошей калибровки?   -  person Aram Gevorgyan    schedule 08.02.2015
comment
к сожалению, это «экспериментальная» часть. попробуйте от 10 до 30 досок, чтобы получить как можно меньше ошибок   -  person berak    schedule 08.02.2015
comment
@berak: и какое допустимое значение ошибки?   -  person Aram Gevorgyan    schedule 08.02.2015
comment
как можно меньше. что-нибудь ›0.5 будет ужасно   -  person berak    schedule 08.02.2015
comment
@berak: Я вижу, я получаю ошибку 1,75, и я думаю, что до калибровки у меня было хуже.   -  person Aram Gevorgyan    schedule 09.02.2015
comment
Значит калибровка так важна для стереоSGMB, все остальное я правильно делаю?   -  person Aram Gevorgyan    schedule 09.02.2015
comment
да, очень даже (к тому же, понять это правильно будет больно..)   -  person berak    schedule 09.02.2015
comment
@berak: Хорошо, спасибо. Не могли бы вы также посоветовать параметры для SBGM?   -  person Aram Gevorgyan    schedule 09.02.2015
comment
извините, но нет, я не могу. они также сильно зависят от ваших изображений.   -  person berak    schedule 09.02.2015


Ответы (1)


Попробуйте использовать этот калибровочный файл — https://github.com/foxymop/3DPoseEstimation/blob/master/src/out_camera_data.yml Я также пытался откалибровать свою камеру, но получить небольшую ошибку очень сложно, и использование этих конфигураций дало мне лучшие результаты, чем попытки найти параметры моей камеры (большинство скорее всего моя камера похожа на ту, что в калибровочном файле). В конце концов, вы можете попытаться вообще не использовать калибровочный файл.

person cyriel    schedule 08.02.2015
comment
извините, но вы не получили основную часть: файл калибровки - это результат калибровки фактической камеры, вы не можете произвольно обмениваться файлами данных там. - person berak; 09.02.2015
comment
пожалуйста, удалите этот ответ, он недействителен. это была чистая случайность, что ваше «решение» сработало в вашем единственном случае. - person berak; 09.02.2015
comment
Я знаю об этом, и, как я писал в своем посте, у меня была похожая проблема - калибровка моей камеры дала очень плохие результаты, поэтому я использовал этот файл калибровки, и он работал намного лучше, чем любая из моих попыток. Я знаю, что это странно, но просто попробуйте, может быть, это сработает и для вас. Также не забывайте, что многие камеры действительно похожи друг на друга (или, по крайней мере, их объективы похожи). Обратите внимание на последнее предложение моего поста. - person cyriel; 09.02.2015
comment
опять же чистая случайность. (не правильный вариант) - person berak; 09.02.2015
comment
Чистая случайность, но вы не можете сказать, будет ли это работать для вас, пока вы не попробуете - возможно, ваша камера похожа на эту (вы не указали, какая у вас камера, поэтому мы можем только догадываться). Также попробуйте без какого-либо файла калибровки - плохой файл калибровки определенно приведет к очень плохим результатам, по крайней мере, отсутствие файла калибровки позволит вам проверить правильность вашего кода StereoSGBM. - person cyriel; 09.02.2015
comment
@cyriel: для меня это тоже было странно, но я хочу попробовать. Но мне нужна калибровка для 2-х камер, а также матрицы трансформации и поворота между ними. - person Aram Gevorgyan; 09.02.2015