2017-01-06 15 views
2

Я пытаюсь получить 3D-координаты с помощью стереокамеры.В чем разница между repjectImageto3D (OpenCV) и несоответствием трехмерным координатам?

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

Второй способ - использовать функцию repjectImageTo3D в 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; 
} 

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

enter image description here

ответ

0

Там не совсем никакой разницы в теории, только в методах. Вы можете рассчитать несоответствие для одиночных совпадающих точек (ваш первый метод) или для каждого пикселя в вашем изображении с помощью метода 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 

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

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

+0

Благодарим вас за ответ. Итак, [X Y Z 1] = inv (K) * [Z * x Z * y Z] то же самое, что и первое уравнение, и нет ли разницы между низкой формулой и reprojectImageTo3D? – user6445248

+0

И я добавил некоторые подробности. Почему эти два метода отличаются по масштабу? – user6445248

+0

@ user6445248 они должны быть эквивалентными (по моему предположению 2). [Это документация оператора stereoSGBM в openCV 2.4] (http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#stereobm-operator). Вы разделили значение оператора sgbm на 16 (вы используете CV_16S)? – marcoresk