Fastest method to convert IplImage IPL_DEPTH_32S to QImage Format_RGB32

我只是一个虾纸丫 提交于 2019-12-02 11:39:39
karlphillip

Before I start, OpenCV uses the BGR format by default. Not RGB! So before creating the QImage you need to convert your IplImage to RGB with:

cvtColor(image, image, CV_BGR2RGB);

Then you can:

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

Note that the constructor above doesn't copy the data as you might be thinking, as the docs states:

The buffer must remain valid throughout the life of the QImage

So if you are having performance issues are not because of the conversion procedure. It is most probably caused by the drawing method you are using (which wasn't shared in the question). To summarize a lot of blah blah blah, you should render the QImage to an OpenGL texture and let the video card do all the drawing for you.

Your question is a bit misleading because your primary objective is not to find the fastest conversion method, but one that actually works since yours don't.

Another important thing to keep in mind, when you said:

image was corrupted after this

you must know that this is completely vague, and it doesn't help us at all because there is a number of causes for this effect, and without the source code is impossible to tell with certainty what are you doing wrong. Sharing the original and the corrupted image might gives some clues to where the problem is.

That's it for now. Good luck.

IPL_DEPTH_32S is greyscale with a 32bit pixel - normally used for depth data rather than an actual 'image', if you are packign a colour image into check what the pixel ordering is.

QImage::Format_ARGB32_Premultiplied is the fastest QImage format because its what the graphics card uses - note that the data order is actually BGRA and the A channel must be at least as large as the pixel, ie 255 if you don't want to use alpha.

There is a RGB2BGRA and BGR2RGBA in cv::cvtColor()

Time ago I found some examples in the internet of how to do that. I improved the examples a bit for how to copy the images in a more easy way. Qt works normally only with char pixels (other image formats are normally called HDR images). I was wondering how you get a video buffer of 32 bit rgb in opencv... I have never seen that !

If you have a color image in opencv you could use this function to allocate memory:

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

to just copy the IplImage to the qt image you could go the easy way and use this function:

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

}
}


}

the following function could be a quicker solution:

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

hope my function helped. Maybe someone know better ways of doing that :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!