Как создать допустимое представление облака точек пары стереоизображений с помощью 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-форме облака точек после недели борьбы. Я никогда не была так счастлива видеть себя раньше!!! ;)