В чем разница между reprojectImageto3D (OpenCV) и несоответствием 3D-координатам?

Я пытаюсь получить 3D-координаты с помощью стереокамеры.

Первый метод заключается в расчете непосредственно по этой формуле. введите описание изображения здесь

Второй способ — использовать reprojectImageTo3D в opencv.

Но я не знаю принципа этого метода.

Результат не в миллиметрах, поэтому трудно подобрать размер.

Пожалуйста, объясните мне разницу между этими двумя методами.

(Первый из этих кодов предназначен для преобразования точечного объекта в 3D-координаты после сопоставления.) (Второй код предназначен для вычисления несоответствия всего стереоизображения с помощью SGBM и вычисления 3D-координат точечного объекта с помощью reprojectImageTo3D.)

*Первый способ

cv::Mat depth(m_input.m_leftImg.size(), CV_32FC3, cv::Scalar::all(0));
int size = feOutput.m_leftKp.size();
for (int i = 0; i < size; i++)
{
    cv::Point pt = cv::Point((int)(feOutput.m_leftKp.at(i).pt.x + 0.5f), (int)(feOutput.m_leftKp.at(i).pt.y + 0.5f));

    depth.at<cv::Vec3f>(pt)[2] = fX * baseLine / (feOutput.m_leftKp.at(i).pt.x - feOutput.m_rightKp.at(i).pt.x);        // Z
    depth.at<cv::Vec3f>(pt)[0] = (feOutput.m_leftKp.at(i).pt.x - cX) * depth.at<cv::Vec3f>(pt)[2] / fX;                 // X
    depth.at<cv::Vec3f>(pt)[1] = (feOutput.m_leftKp.at(i).pt.y - cY) * depth.at<cv::Vec3f>(pt)[2] / fY;                 // Y
}
depth /= 1000.f; //milli-meter to meter

*Второй способ

cv::Mat disparity16S(m_input.m_leftImg.size(), CV_16S);
sgbm->compute(m_input.m_leftImg, m_input.m_rightImg, disparity16S);
cv::Mat xyz;
cv::Matx44d Q = cv::Matx44d(    
    1.0, 0.0, 0.0, -cX,
    0.0, 1.0, 0.0, -cY,
    0.0, 0.0, 0.0, fX,
    0.0, 0.0, -1.0 / baseLine, 0/*(CX - CX) / baseLine*/
);
cv::reprojectImageTo3D(disparity16S, xyz, Q, true);

cv::Mat pointXYZ(xyz.size(), xyz.type(), cv::Scalar::all(0));
for (int i = 0; i < size; i++)
{
    cv::Point pt = cv::Point((int)(feOutput.m_leftKp.at(i).pt.x + 0.5f), (int)(feOutput.m_leftKp.at(i).pt.y + 0.5f));
    pointXYZ.at<cv::Vec3f>(pt) = xyz.at<cv::Vec3f>(pt) / 1000.f;
}

Добавить+ Розовый — это размер метода reprojectImageTo3D, масштабированный до 1/100, а желтый — это размер 1/1000 (мм 2 метра) в первом методе. Если эти два метода одинаковы, почему существует разница в масштабе?

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


person user6445248    schedule 06.01.2017    source источник


Ответы (1)


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

Когда у вас есть несоответствие D, из триангуляции вы получаете глубину Z по первой формуле. Это должно быть «расстояние» от вашей эталонной плоскости изображения (обычно: левая камера).

z = f*b/d 

Когда у вас есть Z, зная, что уравнение проекции утверждает, что для основной камеры (псевдокод)

       f, 0 , cX, 0
 K =   0 , f, cY, 0 
       0 , 0,  1, 0
[x y 1] = 1/Z * K * [X Y Z 1]

что вы можете обратить вспять.

[X Y Z 1] = inv(K)* [Z*x Z*y Z] /*Z is known from disparity */

который нашел ваши x, y, как показано в первом столбце первого изображения. Они находятся в основной (левой) системе отсчета камеры, но если вы хотите, чтобы ваше опубликованное изображение было в правой камере, сделайте 2 предположения.

b is all along x

the two camera planes are perfectly parallel

В общем, для другой камеры вы предполагаете, что b - известный вектор. Может произойти вращение между этими двумя системами отсчета, поэтому также необходимо определить матрицу R). Я думаю, что все эти случаи выражены из другой матрицы Q (полученной из калибровки стереокамеры, например, stereoRectify).

cv::reprojectImageTo3D это только "автоматический метод". Ему нужен параметр камеры и непрерывная карта диспаратности. Он может работать с несоответствием отдельных выбранных точек.

person marcoresk    schedule 06.01.2017
comment
Спасибо за ответ. Итак, [X Y Z 1] = inv (K) * [Z * x Z * y Z] совпадает с первым уравнением и нет ли разницы между формулой low и reprojectImageTo3D? - person user6445248; 09.01.2017
comment
И я добавил некоторые детали. Почему эти два метода различаются по масштабу? - person user6445248; 09.01.2017
comment
@user6445248 user6445248 они должны быть эквивалентны (по моему предположению 2). Это документация по оператору StereoSGBM в openCV 2.4. Вы разделили значение оператора sgbm на 16 (вы используете CV_16S)? - person marcoresk; 09.01.2017
comment
Кажется, это проблема. Я видел, что мне нужно делить на numberOfDisparity в Интернете. Зачем делить? - person user6445248; 09.01.2017
comment
@user6445248 user6445248 Я точно не знаю, почему (полагаю, это должно быть связано с числовым расчетом), просто попробуйте выполнить инструкцию opencv и посмотреть, верны ли результаты (и сообщить об этом здесь). Меньшее значение диспаратности означает более высокие значения глубины, поэтому розовые точки должны достигать желтого диапазона значений глубины. - person marcoresk; 10.01.2017