Solved QImage and OpenCV Mat problem
-
Hi,
IIRC, it will depend on the image format and size. There can be padding involved.
In any case, it's usually done the other way around: load image with OpenCV, apply processing and move then to QImage.
What are you currently doing ?
-
Hi,
currently I am loading a QImage from a file.
Then I encode it to Base64-Format and insert the Base64-String into an xml-structure.This xml is sended through tcp/ip to a server where the server is decoding the Base64-String back to an image. And then I am processing the image with OpenCV.
My current workaround is to save the QImage to hard disk and load again it with OpenCV. That works.
Regards,
Oliver -
That might be a silly question but why not directly encode the file content ?
-
@stvokr
QImage uses a 32-bit alignment, I also had some issues with the bytes: https://forum.qt.io/topic/105321/different-bytes-count-of-qimage -
@SGaist
I will try that, but I need that QImage object directly. It should be possible to display the base64 string directly in a web browser as HTML content.@beecksche
Thanks for that. -
There's no problem with that but you didn't gave much information about your application so it's not easy to provide recommendations.
-
@SGaist
I figured out that the main problem is not transferring the image but loading the image with QImage. Even when I just load the image from harddisk the bytesPerLine is 1004 for an 8 bit pixel image with 1001px width. So as already mentioned from @beecksche the 32-bit alignment will prevent the correct direct conversion from QImage to cv::Mat. -
Afaics OpenCV::Mat also supports padding. Images are always padded so it would be better to teach OpenCV::Mat about it.
-
QImage Mat2QImage(cv::Mat const& src)
{
cv::Mat temp; // make the same cv::Mat
cvtColor(source, temp,CV_BGR2RGB); // cvtColor Makes a copt, that what i need
QImage dest((const uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
dest.bits(); // enforce deep copy, see documentation
// of QImage::QImage ( const uchar * data, int width, int height, Format format )
return dest;
}
// work with QT5.15.0 and OpenCv 4.7.0 -
The decision to always have 4byte aligned scanlines is definitely one of the weirdest things about interoperating QImage with other API's. Most in-memory image formats for other API's are densely packed (at least by default). And it's something you only really notice with odd widths. (And RGBA format is 4 bytes per pixel so it's scanlines are always 4 byte aligned without padding, even for odd-width images.)
If you don't know the quirk, it's annoyingly easy to have a large test suite of different image sizes and formats, and still completely miss the combination of odd width and odd bytes per pixel.
-
@wrosecrans said in QImage and OpenCV Mat problem:
Most in-memory image formats for other API's are densely packed (at least by default).
Then you should never decode a video stream with ffmpeg...
Images in video streams are normally 32 byte aligned nowadays to perfectly match to cpu vector instructions and caches.
The only thing I miss in QImage is to be able to specify this alignment in the ctor like e.g. av_image_alloc() allows.