OpenCV 2.3:将Mat转换为RGBA像素数组

8
我正在尝试使用OpenCV从摄像头中获取帧并使用SFML在窗口中显示它们。
VideoCapture以OpenCV的Mat格式返回帧。为了显示这些帧,SFML需要一个1D像素数组,其uint8格式(据我所知)可与uchar互换。该数组应表示每个像素32位的RGBA值。
因此,我有一个uchar数组,并正在循环遍历Mat数据并复制每个像素:
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时,循环中的某些东西有问题,结果图像变得混乱。

就我所能辨别的来看,要么是循环中的数学计算有误,因此像素被错误地分配,要么Mat数据采用的格式不是BGR。

有什么想法吗?


你所说的“scrambled”具体是什么意思?你能否提供一张结果图像的示例? - sietschie
1
源图像的像素数据没有在目标数组中正确地定位,因此会产生奇怪的交错模式。 - Thew
在从GPU/OpenCL获取数据并将其转储到文件之后,刚刚得到了相同的模式 :D - Mark Essel
3个回答

12

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

这个 LoadFromPixels 方法在 OpenCV 4 中似乎已经不存在了,有替代方法吗? - Jean-Michaël Celerier

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

1

For me worked following code:

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)是一个预乘图像!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接