Плохие результаты на расстоянии при использовании стереокамеры

Я пытаюсь измерить расстояние в режиме реального времени от стереопары до человека, обнаруженного на сцене. Сначала я откалибровал обе камеры по отдельности с помощью шахматной доски 9x6 (размер квадрата 59 мм) и получил среднеквадратичную ошибку между 0,15 и 0,19 для обеих камер. Используя полученные параметры, я откалибровал стереопару, и среднеквадратическая ошибка составила 0,36. Позже я исправил, не исказил и переназначил стереопару, дав мне такой результат: выпрямленное и неискаженное стерео

Сделав это, я вычислил стерео соответствие, используя стерео SGBM. Вот как я это сделал:

Mat imgDisp= Mat(frame1.cols, frame1.rows,CV_16S);

cvtColor(frame1, frame1, CV_BGR2GRAY);
cvtColor(frame2, frame2, CV_BGR2GRAY);

//parameters for stereoSGBM
  stereo.SADWindowSize = 3;
  stereo.numberOfDisparities = 144;
  stereo.preFilterCap = 63;
  stereo.minDisparity = -39;
  stereo.uniquenessRatio = 10;
  stereo.speckleWindowSize = 100;
  stereo.speckleRange = 32;
  stereo.disp12MaxDiff = 1;
  stereo.fullDP = false;
  stereo.P1 = 216;
  stereo.P2 = 864;

double minVal; double maxVal;
minMaxLoc(imgDisp, &minVal, &maxVal);

return imgDisp; 

Я приложил результат от стерео SGBM здесь: карта несоответствия.

Для обнаружения человека в сцене я использовал hog + svm (дектектор людей по умолчанию) и отслеживал этого человека с помощью оптического потока (cvCalcOpticalFlowPyrLK()). Используя карту несоответствия, полученную в процессе стерео соответствия, я получил несоответствие для каждого угла, отслеженного одним человеком, следующим образом:

int x= cornersA[k].x;
int y= cornersA[k].y;

short pixVal= mapaDisp.at<short>(y,x); 
float dispFeatures= pixVal/ 16.0f;

с учетом диспаратности для каждого угла, отслеживаемого для одного человека в сцене, я вычислил максимальный диспарат и вычислил глубину в этом пикселе, используя формулу ((focal * baseline) / disp):

float Disp =maxDisp_v[p];

cout<< "max disp"<< Disp<<endl;
float d = ((double)(879.85* 64.32)/(double)(Disp))/10; //distance in cms.

** для фокусного расстояния я вычислил среднее значение между fx и fy, полученное в параметрах матрицы камер [3x3]:

CM1: [9.0472706037497187e + 02 0. 3.7829164759284492e + 02
0. 8.4576999835299739e + 02 1.8649783393160138e + 02 0. 0. 1.]

CM2: [9.1390904648169953e + 02 0. 3.5700689147467887e + 02 0. 8.5514555697053311e + 02 2.1723345133656409e + 02 0. 0. 1.]

так что fx camera1: 904,7; твоя камера1: 845,7; fx camera2: 913,9; твоя камера2: 855,1

** Результат матрицы T[0,0] совпал с базовой линией, которую я измерял вручную, поэтому я предположил, что это правильная базовая линия.

** из-за квадратного размера шахматной доски в мм, я предположил, что базовая линия должна быть в одной единице, поэтому я положил 64,32 мм в базовой линии.

Результат расстояния - приблизительно. 55 см, но реальное расстояние составляет 300 см. Я проверял много раз, но измеренное расстояние все еще неверно: distanceResult

Помогите мне, пожалуйста! Я понятия не имею, что я делаю не так.

*** Я использую OpenCV 2.4.9 в системе OSX.

2 ответа

Я думаю, что вы делаете ошибку с единицами измерения: фокусное расстояние указывается в пикселях, базовая линия указывается в см. Несоответствие указывается в пикселях. Правильно? По формуле у вас есть пикс * см / пикс = см. Но вы делите это на 10 и получаете дм. Таким образом, у вас есть расстояние около 55 дм, которое в два раза больше, чем 300. Это не плохой случай для вашего подхода.

Вы не можете использовать простую формулу триангуляции параллельных камер на выпрямленных изображениях, потому что вам нужно отменить ректификационные гомографии.

Используйте cv2.reprojectImageTo3D

Другие вопросы по тегам