2012-04-22 11 views
6

Sto tentando di utilizzare OpenCV per acquisire frame da una webcam e visualizzarli in una finestra utilizzando SFML.OpenCV 2.3: Converti matrice in pixel RGBA

VideoCapture restituisce fotogrammi nel formato Mat di OpenCV. Per visualizzare i frame, SFML richiede una matrice 1D di pixel nel suo formato uint8, che (per quanto posso dire) è intercambiabile con uchar. Si prevede che questo array rappresenti 32 bit per pixel RGBA.

Così, ho un array di uchar, e sto loop sui dati Mat e la copia di ogni pixel:

VideoCapture cap(0); 
Mat frame; 
cap >> frame; 

uchar* camData = new uchar[640*480*4]; 
uchar* pixelPtr = frame.data; 
for(int i = 0; i < frame.rows; i++) 
{ 
    for(int j = 0; j < frame.cols; j++) 
    { 
     camData[i*frame.cols + j + 2] = pixelPtr[i*frame.cols + j + 0]; // B 
     camData[i*frame.cols + j + 1] = pixelPtr[i*frame.cols + j + 1]; // G 
     camData[i*frame.cols + j + 0] = pixelPtr[i*frame.cols + j + 2]; // R 
     camData[i*frame.cols + j + 3] = 255; 

    } 
} 
img.LoadFromPixels(640, 480, camData); //Load pixels into SFML Image object for display 

Purtroppo, questo non funziona del tutto. Qualcosa in quel ciclo è sbagliato, poiché l'immagine risultante quando carico e visualizzo camData è criptata.

Per quanto posso discernere, il mio ciclo matematico è sbagliato, quindi i pixel vengono assegnati in modo errato oppure i dati Mat sono in un formato diverso da BGR.

Qualche idea?

+0

Che cosa intendi esattamente con "scrambled"? Potresti postare un esempio dell'immagine risultante? – sietschie

+1

[Esempio] (http://i.imgur.com/dD2fk.png). I dati dei pixel dall'immagine sorgente non finiscono nelle posizioni corrette nell'array di destinazione, quindi rendono strani i pattern di interleaving. – Thew

+0

ha appena avuto lo stesso schema dopo aver estratto i dati da gpu/opencl e scaricato in file: D –

risposta

9

OpenCV può fare tutto il lavoro per voi:

VideoCapture cap(0); 
Mat frame; 
cap >> frame; 

uchar* camData = new uchar[frame.total()*4]; 
Mat continuousRGBA(frame.size(), CV_8UC4, camData); 
cv::cvtColor(frame, continuousRGBA, CV_BGR2RGBA, 4); 
img.LoadFromPixels(frame.cols, frame.rows, camData); 
+0

Funziona perfettamente! Molte grazie. – Thew

1

Per me ha funzionato seguente codice:

VideoCapture capture(0); 
Mat mat_frame; 
capture >> mat_frame; // get a new frame from camera    

// Be sure that we are dealing with RGB colorspace... 
Mat rgbFrame(width, height, CV_8UC3); 
cvtColor(mat_frame, rgbFrame, CV_BGR2RGB); 

// ...now let it convert it to RGBA 
Mat newSrc = Mat(rgbFrame.rows, rgbFrame.cols, CV_8UC4); 
int from_to[] = { 0,0, 1,1, 2,2, 3,3 }; 
mixChannels(&rgbFrame, 2, &newSrc, 1, from_to, 4); 

Il risultato (newsrc) è un'immagine premoltiplicano!

3

Mi piace la risposta accettata meglio ma questo frammento ti aiuta a capire cosa sta succedendo.

for (int i=0; i<srcMat.rows; i++) { 
      for (int j=0; j<srcMat.cols; j++) { 
       int index = (i*srcMat.cols+j)*4; 
       // copy while converting to RGBA order 
       dstRBBA[index + 0] = srcMat[index + 2 ]; 
       dstRBBA[index + 1] = srcMat[index + 1 ]; 
       dstRBBA[index + 2] = srcMat[index + 0 ]; 
       dstRBBA[index + 3] = srcMat[index + 3 ]; 
      } 
     }