плохая карта Disparity с использованием opencv StereoBM

Я пытаюсь использовать StereoBM, чтобы получить карту несоответствия двух изображений. Я попробовал несколько примеров кода и изображений. Работают нормально. Однако, когда я пробую свои собственные изображения, я получаю очень плохую карту, очень шумную.

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

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

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

мои параметры StereoBM

sbm.state->SADWindowSize = 25;
sbm.state->numberOfDisparities = 128;
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;

Мои вопросы

  1. Возникли проблемы с моими изображениями?
  2. Можно ли получить хорошую карту диспаратности без калибровки камеры? Нужно ли мне исправлять изображения перед StereoBM

Спасибо.

Вот мой код для исправления изображения

Mat img_1 = imread( "image1.jpg", CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( "image2.jpg", CV_LOAD_IMAGE_GRAYSCALE );

int minHessian = 430;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );

//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );

//-- Step 3: Matching descriptor vectors with a brute force matcher
BFMatcher matcher(NORM_L1, true);   //BFMatcher matcher(NORM_L2);

std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );

double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < matches.size(); i++ )
{ double dist = matches[i].distance;
    if( dist < min_dist ) min_dist = dist;
    if( dist > max_dist ) max_dist = dist;
}

std::vector< DMatch > good_matches;
vector<Point2f>imgpts1,imgpts2;
for( int i = 0; i < matches.size(); i++ )
{
    if( matches[i].distance <= max(4.5*min_dist, 0.02) ){
        good_matches.push_back( matches[i]);
        imgpts1.push_back(keypoints_1[matches[i].queryIdx].pt);
        imgpts2.push_back(keypoints_2[matches[i].trainIdx].pt);
    }

}

std::vector<uchar> status;
cv::Mat F = cv::findFundamentalMat(imgpts1, imgpts2, cv::FM_8POINT, 3., 0.99, status);   //FM_RANSAC

Mat H1,H2;
cv::stereoRectifyUncalibrated(imgpts1, imgpts1, F, img_1.size(), H1, H2);

cv::Mat rectified1(img_1.size(), img_1.type());
cv::warpPerspective(img_1, rectified1, H1, img_1.size());

cv::Mat rectified2(img_2.size(), img_2.type());
cv::warpPerspective(img_2, rectified2, H2, img_2.size());

StereoBM sbm;
sbm.state->SADWindowSize = 25;
sbm.state->numberOfDisparities = 128;
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;

Mat disp,disp8;
sbm(rectified1, rectified2, disp);

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

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

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

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

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


person fnhdx    schedule 09.03.2016    source источник
comment
Да, их необходимо исправить, как вы можете прочитать в документы   -  person Berriel    schedule 10.03.2016
comment
@Berriel Можно ли исправить изображения без какой-либо информации о камере? Извините, я новичок в этом. Я прочитал stereo_match.cpp. Это требует внутренних параметров камеры.   -  person fnhdx    schedule 10.03.2016


Ответы (2)


  1. С вашими изображениями нет особых проблем. Однако, если время вычислений не имеет решающего значения, я бы посоветовал вам использовать большее разрешение. Кроме того, по возможности лучше нам использовать несжатый формат изображения.

  2. Вы калибруете свои стереокамеры, чтобы исправить стереофонические изображения. Вам действительно нужно исправить изображения, но их также можно исправить без калибровки камеры. Если вам нужно обработать только несколько изображений, вы можете сделать это в Photoshop или подобном, сдвинув или повернув изображения так, чтобы совпадающие точки находились на одной линии. Если у вас есть большее количество изображений для обработки, вы можете сделать это, как вы пытались в своем коде.

Я не просматривал ваш код подробно, но полагаю, вам следует проверить, находятся ли совпадающие точки в одной строке.

В ваших примерах изображений это действительно так, и, используя StereoSGMB вместо StereoBM, я получил лучший, но все же очень шумный результат.

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

Это небольшая настройка параметров для получения хороших результатов в StereoSGMB. Также обратите внимание, что результат для блока сзади намного лучше, чем для объектов спереди, потому что блок имеет текстурированную поверхность.

Вот параметры, которые я использовал:

    Ptr<StereoSGBM> sgbm = StereoSGBM::create(0,    //int minDisparity
                                        96,     //int numDisparities
                                        5,      //int SADWindowSize
                                        600,    //int P1 = 0
                                        2400,   //int P2 = 0
                                        20,     //int disp12MaxDiff = 0
                                        16,     //int preFilterCap = 0
                                        1,      //int uniquenessRatio = 0
                                        100,    //int speckleWindowSize = 0
                                        20,     //int speckleRange = 0
                                        true);  //bool fullDP = false

sgbm->compute(left, right, disp);
person jodis    schedule 13.03.2016
comment
Спасибо за Ваш ответ. Я думаю, что текстурированная поверхность - ключ к успеху. Я получил лучший результат, используя текстурированный объект. - person fnhdx; 14.03.2016

Если ваши камеры плоские, не передавайте матрицу вращения, возвращаемую из stereoRectify, в initUndistort. Процесс выпрямления и неискажения делает эпиполярные линии горизонтальными.

Если все сделано правильно, трехмерные точки должны находиться в одном ряду изображения каждого изображения. Не похоже, чтобы это было так.

person Eharris01    schedule 16.04.2018