2012-04-22 27 views
6

Próbuję użyć OpenCV do przechwytywania klatek z kamery internetowej i wyświetlania ich w oknie przy użyciu SFML.OpenCV 2.3: Konwertuj macie do macierzy pikseli RGBA

VideoCapture zwraca klatki w formacie Mat OpenCV. Aby wyświetlić ramki, SFML wymaga tablicy pikseli 1D w formacie uint8, który (o ile wiem) jest wymienny z uchar. Oczekuje się, że ta macierz będzie reprezentować 32 bity na piksel RGBA.

Tak, mam uchar tablicę, a ja zapętlenie nad danymi matę i kopiując każdy piksel:

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 

Niestety, to nie do końca pracy. Coś w tej pętli jest błędne, ponieważ wynikowy obraz po wczytaniu i wyświetleniu camData jest zakodowany.

O ile mogę się zorientować, albo moja matematyka w pętli jest błędna, więc piksele są przypisane źle, albo dane z Mat są w innym formacie niż BGR.

Wszelkie pomysły?

+0

Co dokładnie masz na myśli przez jajecznicę? Czy mógłbyś podać przykład uzyskanego obrazu? – sietschie

+1

[Przykład] (http://i.imgur.com/dD2fk.png). Dane pikseli z obrazu źródłowego nie kończą się poprawnymi lokalizacjami w docelowej tablicy, więc tworzy dziwne wzory przeplatania. – Thew

+0

po prostu miał ten sam wzór po wyciągnięciu danych z gpu/opencl i wyrzuceniu go do pliku: D –

Odpowiedz

9

OpenCV może zrobić wszystko dla ciebie zadanie:

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

Działa idealnie! Wielkie dzięki. – Thew

1

Dla mnie pracowali następujący kod:

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

wyniku (newsrc) jest mnożenia lewostronnego obraz!

3

Lepsza akceptowana odpowiedź, ale ten fragment pomaga zrozumieć, co się dzieje.

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 ]; 
      } 
     } 
Powiązane problemy