0

将 IplImage IPL_DEPTH_32S 转换为 QImage Format_RGB32 的最快方法是什么?

我需要从 cam 中捕捉图片并以每秒 30 帧的频率在表单上显示。我尝试使用 QImage 构造函数:

QImage qImage((uchar *) image->imageData, image->width, image->height, QImage::Format_RGB32);

但在此之后图像已损坏。那么,我怎样才能快速做到这一点(我认为将逐个像素放入 QImage 不是一个好的决定)?

4

3 回答 3

3

在我开始之前,OpenCV默认使用 BGR 格式。不是RGB!因此,在创建之前,QImage您需要使用以下命令将您的转换IplImage为 RGB:

cvtColor(image, image, CV_BGR2RGB);

那么你也能:

QImage qImage((uchar*) image->imageData, image->width, image->height, QImage::Format_RGB32);

请注意,上面的构造函数不会像您想的那样复制数据,正如文档所述:

缓冲区必须在 QImage 的整个生命周期内保持有效

所以如果你有性能问题不是因为转换过程。这很可能是由您使用的绘图方法引起的(问题中没有共享)。总结一下很多废话,您应该将其渲染QImage到 OpenGL 纹理并让视频卡为您完成所有绘图。

您的问题有点误导,因为您的主要目标不是找到最快的转换方法,而是找到一种真正有效的方法,因为您的方法没有。

另一件重要的事情要记住,当你说:

在此之后图像已损坏

你必须知道这完全是模糊的,它对我们一点帮助也没有,因为造成这种影响的原因有很多,没有源代码是不可能确定你做错了什么的。共享原始图像和损坏的图像可能会为问题所在提供一些线索。

现在就是这样。祝你好运。

于 2012-07-07T02:01:58.707 回答
0

IPL_DEPTH_32S是具有 32 位像素的灰度 - 通常用于深度数据而不是实际的“图像”,如果您将彩色图像打包以检查像素排序是什么。

QImage::Format_ARGB32_Premultiplied是最快的 QImage 格式,因为它是显卡使用的格式 - 请注意,数据顺序实际上是 BGRA,并且 A 通道必须至少与像素一样大,即如果您不想使用 alpha,则为 255。

cv::cvtColor() 中有一个 RGB2BGRA 和 BGR2RGBA

于 2012-07-07T04:42:12.523 回答
0

前段时间我在互联网上找到了一些如何做到这一点的例子。我对示例进行了一些改进,以便以更简单的方式复制图像。Qt 仅适用于 char 像素(其他图像格式通常称为 HDR 图像)。我想知道如何在 opencv 中获得 32 位 rgb 的视频缓冲区...我从未见过!

如果你在 opencv 中有彩色图像,你可以使用这个函数来分配内存:

QImage* allocateqtimagefromcv(IplImage* cvimg)
    {
        //if (cvimg->nChannels==1)
        //  {
        //  return new QImage(cvimg->width,cvimg->height,QImage::Format_Indexed8);
        //  }
        if (cvimg)
            {
            return new QImage(cvimg->width,cvimg->height,QImage::Format_ARGB32);
            }
    }

只需将 IplImage 复制到 qt 图像,您可以使用简单的方法并使用此功能:

void  IplImage2QImage(IplImage *iplImg,QImage* qimg)
{

char *data = iplImg->imageData;
    int channels = iplImg->nChannels;
int h = iplImg->height;
int w = iplImg->width;
for (int y = 0; y < h; y++, data += iplImg->widthStep)
{
for (int x = 0; x < w; x++)
{
char r, g, b, a = 0;
if (channels == 1)
{
r = data[x * channels];
g = data[x * channels];
b = data[x * channels];
}
else if (channels == 3)
{
r = data[x * channels + 2];
g = data[x * channels + 1];
b = data[x * channels];
}

if (channels == 4)
{
a = data[x * channels + 3];
qimg->setPixel(x, y, qRgba(r, g, b, a));
}

}
}


}

以下功能可能是更快的解决方案:

static QImage IplImage2QImage(const IplImage *iplImage)
{
  int height = iplImage->height;
  int width = iplImage->width;
  if (iplImage->depth == IPL_DEPTH_8U && iplImage->nChannels == 3)
  {
      const uchar *qImageBuffer =(const uchar*)iplImage->imageData;
      QImage img(qImageBuffer, width, height, QImage::Format_RGB888);
      return img.rgbSwapped();
  }else{
    //qWarning() << "Image cannot be converted.";
   return QImage();
  }
} 

希望我的功能有所帮助。也许有人知道更好的方法:)

于 2012-07-11T15:10:13.847 回答