2011-12-14 5 views
6

Uso OpenCV per la serie di punti di undestort dopo la calibrazione della videocamera. Il codice segue.Come eliminare i punti nelle coordinate delle riprese della telecamera e ottenere coordinate dell'immagine non distorte corrispondenti?

const int npoints = 2; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file. 
float input_points[npoints][2] = {{0,0}, {2560, 1920}}; 

CvMat * src = cvCreateMat(1, npoints, CV_32FC2); 
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2); 

// fill src matrix 
float * src_ptr = (float*)src->data.ptr; 
for (int pi = 0; pi < npoints; ++pi) { 
    for (int ci = 0; ci < 2; ++ci) { 
     *(src_ptr + pi * 2 + ci) = input_points[pi][ci]; 
    } 
} 

cvUndistortPoints(src, dst, &camera1, &distCoeffs1); 

Dopo il codice sopra dst contiene seguenti numeri:

-8.82689655e-001 -7.05507338e-001 4.16228324e-001 3.04863811e-001 

troppo piccole in confronto con i numeri in src.

Allo stesso tempo se undistort immagine tramite la chiamata:

cvUndistort2(srcImage, dstImage, &camera1, &dist_coeffs1); 

ricevo buona immagine falsato che significa che le coordinate dei pixel non vengono modificate così drasticamente rispetto a punti distinti.

Come ottenere la stessa distorsione per punti specifici come per le immagini? Grazie.

+0

sei sicuro che camera1 e macchina fotografica sono gli stessi? – Sam

+0

sì, lo stesso - ho una domanda fissa. Grazie per avermelo fatto notare Inoltre inizialmente ricevo tale comportamento in EmguCV e poi ho cercato di capire dove viene introdotto tale comportamento: in OpenCV o EmguCV stesso. È apparso in OpenCV. – sergtk

risposta

10

I punti devono essere "non normalizzati" utilizzando la matrice della telecamera.

Più specificamente, dopo opportuno inoltre aggiungere richiamo cvUndistortPoints seguente trasformazione:

double fx = CV_MAT_ELEM(camera1, double, 0, 0); 
double fy = CV_MAT_ELEM(camera1, double, 1, 1); 
double cx = CV_MAT_ELEM(camera1, double, 0, 2); 
double cy = CV_MAT_ELEM(camera1, double, 1, 2); 

float * dst_ptr = (float*)dst->data.ptr; 
for (int pi = 0; pi < npoints; ++pi) { 
    float& px = *(dst_ptr + pi * 2); 
    float& py = *(dst_ptr + pi * 2 + 1); 
    // perform transformation. 
    // In fact this is equivalent to multiplication to camera matrix 
    px = px * fx + cx; 
    py = py * fy + cy; 
} 

Informazioni sulla matrice fotocamera OpenCV 'Camera Calibration and 3D Reconstruction'

UPDATE:

seguito C++ chiamata di funzione dovrebbe funziona anche:

std::vector<cv::Point2f> inputDistortedPoints = ... 
std::vector<cv::Point2f> outputUndistortedPoints; 
cv::Mat cameraMatrix = ... 
cv::Mat distCoeffs = ... 

cv::undistortPoints(inputDistortedPoints, outputUndistortedPoints, cameraMatrix, distCoeffs, cv::noArray(), cameraMatrix); 
1

Essa può essere la dimensione della matrice :)

OpenCV aspetta un vettore di punti - una colonna o una matrice riga con due canali. Ma poiché la tua matrice di input è solo 2 punti e anche il numero di canali è 1, non è possibile capire quale sia l'input, riga o colonna.

Quindi, riempire un tappetino di ingresso più a lungo con i valori falsi, e mantenere solo il primo:

const int npoints = 4; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file. 
float input_points[npoints][4] = {{0,0}, {2560, 1920}}; // the rest will be set to 0 

CvMat * src = cvCreateMat(1, npoints, CV_32FC2); 
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2); 

// fill src matrix 
float * src_ptr = (float*)src->data.ptr; 
for (int pi = 0; pi < npoints; ++pi) { 
    for (int ci = 0; ci < 2; ++ci) { 
     *(src_ptr + pi * 2 + ci) = input_points[pi][ci]; 
    } 
} 

cvUndistortPoints(src, dst, &camera1, &distCoeffs1); 

EDIT

Mentre OpenCV specifica undistortPoints accettano l'ingresso solo a 2 canali, in realtà, si accetta

  • 1-colonna, 2-channel, mat multi-riga o (e questo caso non è documentato)
  • 2 colonna, multi-fila, mat 1-canale o
  • più colonne, 1 fila, mat 2 canali

(come visto in undistort.cpp, linea 390)

Ma un bug interno (o la mancanza di informazioni disponibili), mescola erroneamente il secondo con il terzo, quando il numero di colonne è 2. Quindi, i tuoi dati sono considerati a 2 colonne, 2 righe, 1 canale.

+0

Cosa intendi quando dici 1 canale? Io uso costante CV_32FC2 in cvCreateMat, che significa 2 canali. Grazie. – sergtk

+1

Ho esaminato il codice sorgente della funzione undistortPoints() e la documentazione è errata. Guarda la modifica sopra per i dettagli, per favore – Sam

+0

Ma sembra che la tua risposta sia quella giusta – Sam

Problemi correlati