2012-04-22 12 views
6

Estoy intentando utilizar OpenCV para tomar fotogramas de una cámara web y mostrarlos en una ventana usando SFML.OpenCV 2.3: Convertir Mat a matriz de píxeles RGBA

VideoCapture devuelve marcos en formato Mat de OpenCV. Para mostrar los marcos, SFML requiere una matriz 1D de píxeles en su formato uint8, que (hasta donde yo sé) es intercambiable con uchar. Se espera que esta matriz represente 32 bits por píxel RGBA.

lo tanto, tengo una matriz UCHAR, y estoy bucle a través de los datos de la estera y la copia de cada píxel:

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 

Por desgracia, esto no funciona bien. Algo en ese bucle es incorrecto, ya que la imagen resultante cuando carga y muestra camData está codificada.

Por lo que puedo ver, mis cálculos en el bucle son incorrectos, por lo que los píxeles se asignan incorrectamente, o los datos de Mat están en algún formato que no sea BGR.

¿Alguna idea?

+0

¿A qué se refieren exactamente por scrambled? ¿Podría publicar un ejemplo de la imagen resultante? – sietschie

+1

[Ejemplo] (http://i.imgur.com/dD2fk.png). Los datos de píxeles de la imagen de origen no terminan en las ubicaciones correctas en la matriz de destino, por lo que crea patrones de intercalación extraños. – Thew

+0

acaba de tener el mismo patrón después de tirar datos de la gpu/opencl y volcarlo al archivo: D –

Respuesta

9

OpenCV puede hacer todo el trabajo para usted:

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

¡Funciona a la perfección! Muchas gracias. – Thew

1

Para mí trabajaron siguiente código:

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); 

El resultado (newsrc) es una imagen premultiplicar!

3

Me gusta más la respuesta aceptada, pero este fragmento lo ayuda a comprender lo que está sucediendo.

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 ]; 
      } 
     } 
Cuestiones relacionadas