2012-07-10 22 views
7

Attualmente sto provando a generare punti 3D in base alla coppia di immagini stereo in OpenCV. Questo è stato fatto un bel po 'per quanto posso cercare.Utilizzo di OpenCV per generare punti 3D (presupponendo una configurazione parallela frontale)

Conosco i parametri estrinseci del setup stereo che presumo sia in configurazione parallela frontale (davvero, non è poi così male!). Conosco la lunghezza focale, la linea di base, e assumerò il punto principale come il centro dell'immagine (lo so, lo so ...).

ho calcolare una mappa disparità pseudo-decente utilizzando StereoSGBM e la mano codificati nella matrice Q seguente libro Learning OpenCV di O'Reilly che specifica:

Q = [ 1 0 0  -c_x 
     0 1 0  -c_y 
     0 0 0  f 
     0 0 -1/T_x (c_x - c_x')/T_x ] 

prendo io (C_x, c_y) è il principale punto (che ho specificato nelle coordinate dell'immagine), f è la lunghezza focale (che ho descritto in mm) e T_x è la traduzione tra le due telecamere o linea di base (che ho anche descritto in mm).

int type = CV_STEREO_BM_BASIC; 
double rescx = 0.25, rescy = 0.25; 
Mat disparity, vdisparity, depthMap; 

Mat frame1 = imread("C:\\Users\\Administrator\\Desktop\\Flow\\IMG137.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
Mat frame1L = frame1(Range(0, frame1.rows), Range(0, frame1.cols/2)); 
Mat frame1R = frame1(Range(0, frame1.rows), Range(frame1.cols/2, frame1.cols)); 

resize(frame1L, frame1L, Size(), rescx, rescy); 
resize(frame1R, frame1R, Size(), rescx, rescy); 

int preFilterSize = 9, preFilterCap = 32, disparityRange = 4; 
int minDisparity = 2, textureThreshold = 12, uniquenessRatio = 3; 
int windowSize = 21, smoothP1 = 0, smoothP2 = 0, dispMaxDiff = 32; 
int speckleRange = 0, speckleWindowSize = 0; 

bool dynamicP = false; 

StereoSGBM stereo(minDisparity*-16, disparityRange*16, windowSize, 
    smoothP1, smoothP2, dispMaxDiff, 
    preFilterCap, uniquenessRatio, 
    speckleRange*16, speckleWindowSize, dynamicP); 

stereo(frame1L, frame1R, disparity); 

double m1[3][3] = { { 46, 0, frame1L.cols/2 }, { 0, 46, frame1L.rows/2 }, { 0, 0, 1 } }; 
double t1[3] = { 65, 0, 0 }; 
double q[4][4] = {{ 1, 0, 0, -frame1L.cols/2.0 }, { 0, 1, 0, -frame1L.rows/2.0 }, { 0, 0, 0, 46 }, { 0, 0, -1.0/65, 0 }}; 
Mat cm1(3, 3, CV_64F, m1), cm2(3, 3, CV_64F, m1), T(3, 1, CV_64F, t1); 
Mat R1, R2, P1, P2; 
Mat Q(4, 4, CV_64F, q); 

//stereoRectify(cm1, Mat::zeros(5, 1, CV_64F), cm2, Mat::zeros(5, 1, CV_64F), frame1L.size(), Mat::eye(3, 3, CV_64F), T, R1, R2, P1, P2, Q); 

normalize(disparity, vdisparity, 0, 256, NORM_MINMAX); 
//convertScaleAbs(disparity, disparity, 1/16.0); 
reprojectImageTo3D(disparity, depthMap, Q, true); 
imshow("Disparity", vdisparity); 
imshow("3D", depthMap); 

Così ho alimentano la mappa disparità risultante da StereoSGBM e che matrice Q per ottenere punti 3D, che scrivo in un file strati.

Ma il risultato è questo: http://i.stack.imgur.com/7eH9V.png

divertenti da guardare, ma non quello che mi serve :(ho letto online che ottiene risultati migliori dopo aver diviso la mappa disparità del 16 e in effetti sembrava leggermente meglio (. in realtà sembra che ci fosse una macchina fotografica che ha preso il colpo)

Questa è la mia mappa disparità se siete interessati:!. http://i.stack.imgur.com/lNPkO.png

ho capito che senza callibration, non è certo andare a guardare come il miglior 3d proiezione, ma mi aspettavo qualcosa di meglio ...

Qualche suggerimento?

risposta

0

Sotto ipotesi fronto-Parrallel, la relazione tra disparità e profondità 3D è: d = f*T/Z, dove d è la disparità, f è la lunghezza focale, T è basale e Z è la profondità 3D. Se si considera il centro dell'immagine come il punto principale, il sistema di coordinate 3D viene regolato. Poi per un pixel (px,py), coordinata 3D (X, Y, Z) è:

X = (px-cx)*Z/f, Y = (py- cy)*Z/f, Z = f*T/d,

dove cx, cy sono la coordinata del pixel del centro dell'immagine.

L'immagine della disparità sembra buona e può generare nuvole di punti 3D ragionevoli.

Un browser disparità semplice su github.

Problemi correlati