Получение плоского облака точек из карты несоответствий

Я пытался создать облако точек из пары исправленных стереоизображений. Сначала я получил карту несоответствия, используя реализацию opencv sgbm. Затем я преобразовал его в облако точек, используя следующий код:

[for (int u=0; u < left.rows; ++u)
                {
                        for (int v=0; v < left.cols; ++v)
                        {
                                if(disp.at<int>(u,v)==0)continue;
                                pcl::PointXYZRGB p;
                                p.x = v;
                                p.y = u;
                                p.z = (left_focalLength * baseLine * 0.01/ disp.at<int>(u,v));
                                std::cout << p.z << std::endl;
                                cv::Vec3b bgr(left.at<cv::Vec3b>(u,v));
                                p.b = bgr\[0\];
                                p.g = bgr\[1\];
                                p.r = bgr\[2\];
                                pc.push_back(p);
                        }
                }][1]

left - левое изображение, disp - изображение несоответствия вывода в cv_16s. Правильно ли мое несоответствие с преобразованием pcl или это проблема со значениями несоответствия?

Я приложил снимок экрана с картой несоответствия, облаком точек и исходным левым изображением.

Спасибо!

снимок экрана


person Karnik Ram    schedule 07.01.2017    source источник


Ответы (1)


Я не уверен в этом языке, но заметил одну вещь:
Предполагая, что эта строка преобразует disparty в depth (Z)

p.z = (left_focalLength * baseLine * 0.01/ disp.at<int>(u,v));

Что такое 0,01? Если этот расчет дает вам диапазон глубин (Z) от 1 до 10, этот коэффициент уменьшает ваш диапазон с 0,01 до 0,1. Глубина всегда близка к нулю, и у вас есть плоское изображение (плоское изображение = постоянная глубина).

PS Я не вижу в вашем коде преобразования X, Y из значений пикселей u, v со значением Z. Что-то типа

X = u*Z/f
person marcoresk    schedule 07.01.2017
comment
Спасибо за ответ. Значение 0,01 предназначено для преобразования значений фокусного расстояния и базовой линии в см. Я использовал функцию opencv CalibrationMatrixValues, которая выводит эти значения в мм из внутренней матрицы камеры. Однако теперь я использую функцию reprojectImageTo3D opencv для сопоставления глубины и несоответствия, и я получаю трехмерные результаты, но их все еще очень не хватает - drive.google.com/file/d/0B_2Iwz6JbA4pVi0tWVEyUFc1Tlk/ - person Karnik Ram; 08.01.2017
comment
@KarnikRam Я подумал об еще одной (возможно, глупой) детали: знаете ли вы, что алгоритм sgbm обеспечивает значение несоответствия в 16 раз больше? (вам нужно разделить на 16, чтобы получить реальное значение) - person marcoresk; 08.01.2017
comment
Да :) Вы можете найти мой полный код здесь - drive.google.com / file / d / 0B_2Iwz6JbA4pSHV0TVR2TG9INk0 /; вы можете игнорировать функции LoadMetadata и LoadCalibration. - person Karnik Ram; 09.01.2017
comment
@KarnikRam Я не привык к C ++, но если эти две строки являются последовательными, computeDisparity(left, right, disp); cv::reprojectImageTo3D(disp, xyz, Q, false, CV_32F); где вы делите disp на 16? (Я вижу, вы масштабировали disp8 от 0 до 255, но это другое дело. Вы использовали disp в 3D-реконструкции). - person marcoresk; 10.01.2017
comment
Привет, я тоже использовал disp8 для computeDisparity. Без изменений. - person Karnik Ram; 12.01.2017
comment
@KarnikRam, конечно: disp8 - это масштабированное, а не реальное значение. Disp8 = disp*255/(numdisparities*16), правильно? У меня был вопрос: а где в вашем коде деление на 16? Попробуйте что-нибудь вроде disp2 = disp/16, затем используйте disp2 для перепроецирования. Если это не сработает, проблема может быть в другом месте. - person marcoresk; 12.01.2017
comment
Эй, да, это тоже пробовали. Не так много изменений в выводе: / - person Karnik Ram; 19.01.2017