2012-04-22 28 views
6

Bir web kamerasından çerçeveler almak ve SFML kullanarak bir pencerede görüntülemek için OpenCV'yi kullanmaya çalışıyorum.OpenCV 2.3: Mat'ı RGBA piksel dizisine dönüştürme

VideoCapture, OpenCV'nin Mat biçimindeki kareleri döndürür. Çerçeveleri görüntülemek için SFML, uint8 biçiminde bir 1D piksel dizisi gerektirir; bu, (anlayabildiğim kadarıyla) uchar ile değiştirilebilir. Bu dizinin piksel RGBA başına 32 bit göstermesi bekleniyor.

Yani, bir UCHAR dizi var ve Mat veriler üzerinden döngü ve her pikseli taklit ediyorum:

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 

Maalesef bu oldukça çalışır değil. Bu döngüdeki bir şey yanlıştır, çünkü camData yüklendiğinde ve görüntülediğimde ortaya çıkan görüntü şifrelenmiştir.

Fark edebildiğime göre, döngüdeki matematiğim yanlıştır, dolayısıyla pikseller yanlış atanır veya Mat verisi BGR dışında bir biçimde olur.

Herhangi bir fikrin var mı?

+0

Tam olarak ne demek donduruyor? Ortaya çıkan görüntünün bir örneğini gönderebilir misiniz? – sietschie

+1

[Örnek] (http://i.imgur.com/dD2fk.png). Kaynak görüntüdeki piksel verileri, hedef dizideki doğru konumlarda sona ermiyor, bu nedenle tuhaf aralama desenleri oluşturuyor. – Thew

+0

, gpu/opencl'den veriyi geri yükledikten ve dosyaya döktükten hemen sonra aynı desene sahipti: D –

cevap

9

OpenCV sizin için tüm iş yapabilirsiniz: Benim için

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

Mükemmel çalışıyor! Çok teşekkürler. – Thew

1

çalıştı kod aşağıdadır:

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

sonuç (newsrc) bir premultiply resimdir!

3

Kabul edilen yanıtı daha çok beğeniyorum ama bu kod parçacığı neler olup bittiğini anlamanıza yardımcı oluyor.

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 ]; 
      } 
     } 
İlgili konular