Failed conversion of a QImage image to a CV image

-1

I am new to both opencv and opencv. What I am doing is to convert a QImage image to an opencv Mat image, and then display both of them. Here is my code for this conversion:

     i = new QImage("lena.png");
    QImage lena = i->scaled(labW,labH,Qt::IgnoreAspectRatio);

    //Original
    QImage lenaRGB = lena.convertToFormat(QImage::Format_RGB888);
    ui->imgWindow->setPixmap(QPixmap::fromImage(lena,Qt::AutoColor));

    //method 1
    Mat lena_cv, out;
    QImage lena2 = lenaRGB.rgbSwapped();
    QImage swapped = lena2;
    swapped = swapped.rgbSwapped();
    lena_cv = Mat(swapped.width(),swapped.height(),CV_8UC3, swapped.bits(),swapped.bytesPerLine()).clone();
    namedWindow("CV Image");
    imshow("CV Image", lena_cv);

    //method 2
    Mat out2,out3;
    out2.create(Size(lena2.width(),lena2.height()),CV_8UC3);
    int width = lena2.width();
    int height = lena2.height();
    memcpy(out2.data, lena2.bits(), sizeof(char)*width*height*3);
    cvtColor(out2,out3,CV_RGB2GRAY);
    namedWindow("CV Image2");
    imshow("CV Image2",out3);

Both of the above two conversions cannot yield desired images, as shown below: enter image description here

It is also noted that the conversion cannot proceed without using rgbSwapped, i.e.,:

lena_cv = Mat(lenaRGB.width(),lenaRGB.height(),CV_8UC3, lenaRGB.bits(),lenaRGB.bytesPerLine());

because: enter image description here

enter image description here

The resulting image lena_cv cannot be displayed. If an additional step to convert lena_cv to BGR format using cvtColor before image display:

    Exception at 0x7ffdff394008, code: 0xe06d7363: C++ exception, flags=0x1  
   (execution cannot be continued) (first chance) at c:\opencv-3.2.0
    \sources\modules\core\src\opencl\runtime\opencl_core.cpp:278

This indicates the post conversion to BGR fails. I am not sure RGB to BGR conversion (of QImage) is necessary or not for converting QImage to CV image. Can anyone help identify the issue with the above codes. Thanks :)

qt
opencv
asked on Stack Overflow Feb 19, 2018 by jingweimo • edited Feb 20, 2018 by jingweimo

1 Answer

1

The "skew" in the third image is almost likely a result of assuming that each scan line occupies exactly width*3 bytes. There's typically a "stride" (or "steps") factor with each row in many image formats image such that the number of bytes per row is on some 4-byte or 16-byte boundary. Fortunately, QImage has a helper method called bytesPerLine that tells you how long each source row is.

So instead of this:

memcpy(out2.data, lena2.bits(), sizeof(char)*width*height*3);

Do this:

unsigned char* src = lena2.bits();
unsigned char* dst = out2.data;
int stride = lena2.bytesPerLine();
for (int row = 0; row < height; row++)
{
    memcpy(dst + width*3*row, src+row*stride, width*3); // copy a single row, accounting for stride bytes
}

All of this assume it's the QImage that has the stride bytes and not the target Mat image you are transforming the bits too. If I have this backwards, then adjust the code to account for the steps member of Mat. (I don't see you using this, so I'm willing to be the above code is what you need).

The "blue" image is mostly likely just the RGB color bytes needing to be swapped for every pixel. Not sure why you are calling rgbSwapped unless that was the effect you were going for. Oh wait, you're probably referring to that noise effect at the bottom of the image. I'm willing to bet you need to think about "stride" bytes as well here too.

answered on Stack Overflow Feb 19, 2018 by selbie • edited Feb 19, 2018 by selbie

User contributions licensed under CC BY-SA 3.0