Как создать допустимое представление облака точек пары стереоизображений с помощью OpenCV 3.0 StereoSGBM и PCL

недавно я начал работать с OpenCV 3.0, и моя цель-захватить пару стереоизображений из набора стереокамер, создать правильную карту несоответствия, преобразовать карту несоответствия в 3D-облако точек и, наконец, показать результирующее облако точек в средстве просмотра облака точек с помощью PCL.

Я уже выполнил калибровку камеры, и результирующая калибровка RMS составляет 0,4

вы можете найти мои пары изображений (левое изображение)1 и (справа Image)2 в ссылках ниже. Я использую StereoSGBM для создания изображения несоответствия. Я также использую track-bars для настройки параметров функции StereoSGBM, чтобы получить лучшее изображение несоответствия. К сожалению, я не могу опубликовать свой образ несоответствия, так как я новичок в StackOverflow и не имею достаточной репутации для публикации более двух ссылок на изображения!

после получения изображения несоответствия ("disp" в приведенном ниже коде) я использую функцию reprojectImageTo3D () для преобразования информация о несоответствии изображения координате XYZ 3D, а затем я преобразую результаты в массив точек" pcl::PointXYZRGB", чтобы их можно было показать в средстве просмотра облаков точек PCL. После выполнения необходимого преобразования, то, что я получаю как облако точек,-это глупое облако точек пирамиды, которое не имеет никакого смысла. Я уже прочитал и попробовал все предложенные методы по следующим ссылкам:

1-http: //blog.martinperis.com/2012/01/3d-reconstruction-with-opencv-and-point.html

2-http: //stackoverflow.com/questions/13463476/opencv-stereorectifyuncalibrated-to-3d-point-cloud

3-http: //stackoverflow.com/questions/22418846/reprojectimageto3d-in-opencv

и ни один из них не работал!!!

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

pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointcloud(new   pcl::PointCloud<pcl::PointXYZRGB>());
    Mat xyz;
    reprojectImageTo3D(disp, xyz, Q, false, CV_32F);
    pointcloud->width = static_cast<uint32_t>(disp.cols);
    pointcloud->height = static_cast<uint32_t>(disp.rows);
    pointcloud->is_dense = false;
    pcl::PointXYZRGB point;
    for (int i = 0; i < disp.rows; ++i)
        {
            uchar* rgb_ptr = Frame_RGBRight.ptr<uchar>(i);
            uchar* disp_ptr = disp.ptr<uchar>(i);
            double* xyz_ptr = xyz.ptr<double>(i);

            for (int j = 0; j < disp.cols; ++j)
            {
                uchar d = disp_ptr[j];
                if (d == 0) continue;
                Point3f p = xyz.at<Point3f>(i, j);

                point.z = p.z;   // I have also tried p.z/16
                point.x = p.x;
                point.y = p.y;

                point.b = rgb_ptr[3 * j];
                point.g = rgb_ptr[3 * j + 1];
                point.r = rgb_ptr[3 * j + 2];
                pointcloud->points.push_back(point);
            }
        }
    viewer.showCloud(pointcloud);

1 ответов


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

ничего плохого в алгоритме преобразования из изображения несоответствия в 3D XYZ (и, в конечном итоге, в облако точек) не было. Проблема заключалась в расстоянии объектов (которые я фотографировал) до камер и количестве информации, доступной для алгоритмов StereoBM или StereoSGBM для обнаружения сходства между двумя изображениями (пара изображений). В чтобы получить правильное облако точек 3D, необходимо иметь хорошее изображение несоответствия, а чтобы иметь хорошее изображение несоответствия (при условии, что вы выполнили хорошую калибровку), убедитесь в следующем:

1 - должно быть достаточно обнаруживаемых и различимых общих функций, доступных между двумя кадрами (правый и левый кадр). Причина в том, что алгоритмы StereoBM или StereoSGBM ищут общие черты между двумя кадрами, и их можно легко обмануть подобными вещи в двух рамках, которые могут не обязательно принадлежать одним и тем же объектам. Я лично думаю, что эти два алгоритма сопоставления имеют много возможностей для совершенствования. Так что остерегайтесь того, на что вы смотрите своими камерами.

2-объекты, представляющие интерес (те, которые вас интересуют, чтобы иметь свою 3D модель облака точек) должны быть в пределах определенного расстояния до ваших камер. Чем больше базовая линия (базовая линия-это расстояние между двумя камерами), тем дальше ваши объекты интерес (цели) может быть.

шумное и искаженное изображение несоответствия никогда не создает хорошее облако точек 3D. Одна вещь, которую вы можете сделать, чтобы улучшить свои изображения несоответствия, - это использовать дорожки в своих приложениях, чтобы вы могли настроить параметры StereoSBM или StereoSGBM, пока не увидите хорошие результаты (четкое и плавное изображение несоответствия). Ниже приведен небольшой и простой пример того, как создавать трековые бары (я написал его как можно проще). Используйте по мере необходимости:

 int PreFilterType = 0, PreFilterCap = 0, MinDisparity = 0, UniqnessRatio = 0, TextureThreshold = 0,
    SpeckleRange = 0, SADWindowSize = 5, SpackleWindowSize = 0, numDisparities = 0, numDisparities2 = 0, PreFilterSize = 5;


            Ptr<StereoBM> sbm = StereoBM::create(numDisparities, SADWindowSize);  

while(1)
{
            sbm->setPreFilterType(PreFilterType);
            sbm->setPreFilterSize(PreFilterSize);  
            sbm->setPreFilterCap(PreFilterCap + 1);
            sbm->setMinDisparity(MinDisparity-100);
            sbm->setTextureThreshold(TextureThreshold*0.0001);
            sbm->setSpeckleRange(SpeckleRange);
            sbm->setSpeckleWindowSize(SpackleWindowSize);
            sbm->setUniquenessRatio(0.01*UniqnessRatio);
            sbm->setSmallerBlockSize(15);
            sbm->setDisp12MaxDiff(32);

            namedWindow("Track Bar Window", CV_WINDOW_NORMAL);
            cvCreateTrackbar("Number of Disparities", "Track Bar Window", &PreFilterType, 1, 0);
            cvCreateTrackbar("Pre Filter Size", "Track Bar Window", &PreFilterSize, 100);
            cvCreateTrackbar("Pre Filter Cap", "Track Bar Window", &PreFilterCap, 61);
            cvCreateTrackbar("Minimum Disparity", "Track Bar Window", &MinDisparity, 200);
            cvCreateTrackbar("Uniqueness Ratio", "Track Bar Window", &UniqnessRatio, 2500);
            cvCreateTrackbar("Texture Threshold", "Track Bar Window", &TextureThreshold, 10000);
            cvCreateTrackbar("Speckle Range", "Track Bar Window", &SpeckleRange, 500);
            cvCreateTrackbar("Block Size", "Track Bar Window", &SADWindowSize, 100);
            cvCreateTrackbar("Speckle Window Size", "Track Bar Window", &SpackleWindowSize, 200);
            cvCreateTrackbar("Number of Disparity", "Track Bar Window", &numDisparities, 500);

            if (PreFilterSize % 2 == 0)
            {
                PreFilterSize = PreFilterSize + 1;
            }


            if (PreFilterSize2 < 5)
            {
                PreFilterSize = 5;
            }

            if (SADWindowSize % 2 == 0)
            {
                SADWindowSize = SADWindowSize + 1;
            }

            if (SADWindowSize < 5)
            {
                SADWindowSize = 5;
            }


            if (numDisparities % 16 != 0)
            {
                numDisparities = numDisparities + (16 - numDisparities % 16);
            }
        }
}

Если вы не получая должных результатов и сглаживая несоответствие изображения, не разочаровывайтесь. Попробуйте использовать образцы изображений OpenCV (тот, в котором есть оранжевая настольная лампа) с вашим алгоритмом, чтобы убедиться, что у вас есть правильный трубопровод, а затем попробуйте делать снимки с разных расстояний и играть с параметрами StereoBM/StereoSGBM, пока вы не сможете получить что-то полезное. Я использовал свое собственное лицо для этой цели, и поскольку у меня была очень маленькая базовая линия, я подошел очень близко к своим камерам (вот ссылка на мое 3D-лицо изображение облака точек, и Эй, не смей смеяться!!!)1.Я был очень рад видеть себя в 3D-форме облака точек после недели борьбы. Я никогда не была так счастлива видеть себя раньше!!! ;)