How to convert an OpenCV cv::Mat to QImage
I am wondering how would I convert the OpenCV C++ standard cv::Mat type to QImage. I have been searching around, but have no luck. I have found some code that converts the IPlimage to QImage, but that is not what I want. Thanks.
Solution 1:
Michal Kottman's answer is valid and give expected result for some images but it'll fail on some cases. Here is a solution i found to that problem.
QImage imgIn= QImage((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);
Difference is adding img.step part. qt won't complain without it but some images won't show properly without it. Hope this will help.
Solution 2:
Here is code for 24bit RGB and grayscale floating point. Easily adjustable for other types. It is as efficient as it gets.
QImage Mat2QImage(const cv::Mat3b &src) {
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y) {
const cv::Vec3b *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x) {
destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
}
}
return dest;
}
QImage Mat2QImage(const cv::Mat_<double> &src)
{
double scale = 255.0;
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y) {
const double *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x) {
unsigned int color = srcrow[x] * scale;
destrow[x] = qRgba(color, color, color, 255);
}
}
return dest;
}
Solution 3:
To convert from cv::Mat
to QImage
, you could try to use the QImage(uchar * data, int width, int height, Format format)
constructor as follows (mat
is a cv::Mat
) :
QImage img((uchar*)mat.data, mat.cols, mat.rows, QImage::Format_RGB32);
It is more efficient than manually converting the pixels to the QImage
, but you have to keep the original cv::Mat
image in memory. It can be easily converted to a QPixmap
and displayed using a QLabel
:
QPixmap pixmap = QPixmap::fromImage(img);
myLabel.setPixmap(pixmap);
Update
Because OpenCV uses BGR order by default, you should first use cvtColor(src, dst, CV_BGR2RGB)
to get an image layout that Qt understands.
Update 2:
If the image you are trying to show has nonstandard stride (when it is non-continuous, submatrix), the image may appeard distorted. In this case, it is better to explicitly specify the stride using cv::Mat::step1()
:
QImage img((uchar*)mat.data, mat.cols, mat.rows, mat.step1(), QImage::Format_RGB32);