2012-04-22 273 views
6

我試圖使用OpenCV從網絡攝像頭抓取幀,並使用SFML將它們顯示在窗口中。OpenCV 2.3:將Mat轉換爲RGBA像素陣列

VideoCapture以OpenCV的Mat格式返回幀。爲了顯示這些幀,SFML需要一個uint8格式的一維像素數組,它(據我所知)可以與uchar進行互換。預計該陣列將代表每像素RGBA 32位。

所以,我有一個UCHAR陣列,而我遍歷該墊的數據和複製的每個像素:

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 

不幸的是,這完全不是那麼回事。那個循環中的東西是錯誤的,因爲當我加載並顯示camData時產生的圖像被加擾。

據我所知,無論是我在循環中的算術是錯誤的,所以像素分配錯誤,或墊數據是在某種格式以外的BGR。

任何想法?

+0

你究竟是什麼意思炒蛋?你可能會張貼結果圖像的例子嗎? – sietschie 2012-04-22 06:32:10

+1

[示例](http://i.imgur.com/dD2fk.png)。來自源圖像的像素數據沒有在目的地陣列中的正確位置結束,因此它會產生奇怪的交錯模式。 – Thew 2012-04-22 07:26:33

+0

從gpu/opencl中提取數據並將其轉儲到文件後具有相同的模式:D – 2013-10-24 15:17:53

回答

9

的OpenCV能爲你做的所有工作:

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

完美地工作!非常感謝。 – Thew 2012-04-22 19:24:29

1

爲我工作下面的代碼:

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

結果(newSrc)是預乘圖像!

3

我更喜歡接受的答案,但這段代碼可以幫助您瞭解發生了什麼。

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