how to convert an opencv cv::Mat to qimage
up vote
32
down vote
favorite
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
c++ qt opencv qimage
add a comment |
up vote
32
down vote
favorite
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
c++ qt opencv qimage
It will be useful if such code exists, but there are some issues in writing it: cv::Mat support more data types than QImage, cv::Mat supports multiple channels, should the data be copied or wrapped around the original data...
– Hristo Hristov
Feb 17 '11 at 9:36
add a comment |
up vote
32
down vote
favorite
up vote
32
down vote
favorite
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
c++ qt opencv 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
c++ qt opencv qimage
c++ qt opencv qimage
edited Dec 8 '11 at 19:21
karlphillip
73.4k26183346
73.4k26183346
asked Feb 17 '11 at 9:14
Hien
64931016
64931016
It will be useful if such code exists, but there are some issues in writing it: cv::Mat support more data types than QImage, cv::Mat supports multiple channels, should the data be copied or wrapped around the original data...
– Hristo Hristov
Feb 17 '11 at 9:36
add a comment |
It will be useful if such code exists, but there are some issues in writing it: cv::Mat support more data types than QImage, cv::Mat supports multiple channels, should the data be copied or wrapped around the original data...
– Hristo Hristov
Feb 17 '11 at 9:36
It will be useful if such code exists, but there are some issues in writing it: cv::Mat support more data types than QImage, cv::Mat supports multiple channels, should the data be copied or wrapped around the original data...
– Hristo Hristov
Feb 17 '11 at 9:36
It will be useful if such code exists, but there are some issues in writing it: cv::Mat support more data types than QImage, cv::Mat supports multiple channels, should the data be copied or wrapped around the original data...
– Hristo Hristov
Feb 17 '11 at 9:36
add a comment |
11 Answers
11
active
oldest
votes
up vote
32
down vote
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.
3
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400)cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.
– Nolan Amy
Sep 7 '12 at 18:50
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.
– MeloMCR
Sep 19 '12 at 13:56
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
add a comment |
up vote
29
down vote
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;
}
1
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
add a comment |
up vote
23
down vote
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);
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
2
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded byimread
, or converted to appropriate type.
– Michal Kottman
Feb 18 '11 at 8:39
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
1
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
1
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
add a comment |
up vote
3
down vote
Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR);
Mat dest;
cvtColor(opencv_image, dest,CV_BGR2RGB);
QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888);
This is what worked for me. I modified Michal Kottman's code above.
add a comment |
up vote
2
down vote
cv::Mat has a conversion operator to IplImage, so if you have something that converts the IplImage to a QImage, just use that (or make the - probably minor - adjustments to take the cv::Mat directly, the memory layout is the same, it's "just" the header that is different.)
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
add a comment |
up vote
2
down vote
I have the same problem as you too, so I develop four functions to alleviate my pain, they are
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);
QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);
cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);
cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
These functions can handle the images with 1, 3, 4 channels, every pixel must occupy one byte only(CV_8U->Format_Indexed8, CV_8UC3->QImage::Format_RGB888, CV_8UC4->QImage::Format_ARGB32), I do not deal with other types yet(QImage::Format_RGB16, QImage::Format_RGB666 and so on). The codes are located
at github.
The key concepts of **transform mat to Qimage ** are
/**
* @brief copy QImage into cv::Mat
*/
struct mat_to_qimage_cpy_policy
{
static QImage start(cv::Mat const &mat, QImage::Format format)
{
//The fourth parameters--mat.step is crucial, because
//opencv may do padding on every row, you need to tell
//the qimage how many bytes per row
//The last thing is if you want to copy the buffer of cv::Mat
//to the qimage, you need to call copy(), else the qimage
//will share the buffer of cv::Mat
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
};
struct mat_to_qimage_ref_policy
{
static QImage start(cv::Mat &mat, QImage::Format format)
{
//every thing are same as copy policy, but this one share
//the buffer of cv::Mat but not copy
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
};
The key concepts of transform cv::Mat to Qimage
are
/**
* @brief copy QImage into cv::Mat
*/
struct qimage_to_mat_cpy_policy
{
static cv::Mat start(QImage const &img, int format)
{
//same as convert mat to qimage, the fifth parameter bytesPerLine()
//indicate how many bytes per row
//If you want to copy the data you need to call clone(), else QImage
//cv::Mat will share the buffer
return cv::Mat(img.height(), img.width(), format,
const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
}
};
/**
* @brief make Qimage and cv::Mat share the same buffer, the resource
* of the cv::Mat must not deleted before the QImage finish
* the jobs.
*/
struct qimage_to_mat_ref_policy
{
static cv::Mat start(QImage &img, int format)
{
//same as copy policy, but this one will share the buffer
return cv::Mat(img.height(), img.width(), format,
img.bits(), img.bytesPerLine());
}
};
If would be good if some one can extend these functions and make them support more types, please inform me if there are any bugs.
add a comment |
up vote
1
down vote
This post shows how to convert a QImage
to OpenCV's IplImage
and vise-versa.
After that, if you need help to convert between IplImage*
to cv::Mat
:
// Assume data is stored by:
// IplImage* image;
cv::Mat mat(image, true); // Copies the data from image
cv::Mat mat(image, false); // Doesn't copy the data!
It's a hack, but will get the job done.
add a comment |
up vote
1
down vote
Use the static function convert16uc1 for the depth image:
QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
quint8 value = (quint8) ((*(pSource)) >> 8);
*(pDest++) = value; // B
*(pDest++) = value; // G
*(pDest++) = value; // R
*(pDest++) = 0; // Alpha
pSource++;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
quint8* pSource = source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
add a comment |
up vote
0
down vote
It might seem silly, but saving the image to a folder and then reading into a QImage object seemed to me the quickest way.
Mat x = imread("--.jpg");
imwrite("x.jpg", x);
QImage img("x.jpg");
add a comment |
up vote
0
down vote
OpenCV loads images into a Mat
in Blue-Green-Red (BGR) format by default, while QImage
expects RGB. This means that if you convert a Mat
to QImage
, the blue and red channels will be swapped. To fix this, before constructing the QImage
, you need to change the BRG format of your Mat
to RGB, via the cvtColor
method using argument CV_BGR2RGB
, like so:
Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
Alternatively, use rgbSwapped()
on the QImage
QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());
add a comment |
up vote
-1
down vote
This did the trick for me. It's a little dodgy, has terrible performance (as pointed out in the comments), but works with all color formats I have thrown at it so far, and it is also very simple to do.
The procedure is as follows:
cv::Mat image = //...some image you want to display
// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);
// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
Done!
If you, say, want to display it in a QLabel, then continue with:
// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));
I personally use this for a simple image editor.
3
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
add a comment |
11 Answers
11
active
oldest
votes
11 Answers
11
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
32
down vote
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.
3
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400)cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.
– Nolan Amy
Sep 7 '12 at 18:50
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.
– MeloMCR
Sep 19 '12 at 13:56
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
add a comment |
up vote
32
down vote
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.
3
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400)cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.
– Nolan Amy
Sep 7 '12 at 18:50
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.
– MeloMCR
Sep 19 '12 at 13:56
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
add a comment |
up vote
32
down vote
up vote
32
down vote
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.
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.
answered Sep 7 '12 at 5:40
chAmi
1,04931525
1,04931525
3
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400)cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.
– Nolan Amy
Sep 7 '12 at 18:50
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.
– MeloMCR
Sep 19 '12 at 13:56
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
add a comment |
3
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400)cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.
– Nolan Amy
Sep 7 '12 at 18:50
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.
– MeloMCR
Sep 19 '12 at 13:56
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
3
3
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)
image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400) cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.– Nolan Amy
Sep 7 '12 at 18:50
This is essentially what OpenCV uses internally to convert (code.opencv.org/projects/opencv/repository/revisions/…, line 2389)
image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
Also (approximately, line 2400) cvConvertImage(mat, image2Draw_mat, CV_CVTIMG_SWAP_RB);
to convert from BGR to RGB.– Nolan Amy
Sep 7 '12 at 18:50
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.– MeloMCR
Sep 19 '12 at 13:56
img.step
makes all the difference. I was having weird problems with this conversion, including having the resulting image show distorted and with the wrong colors. Testing a little bit I got the same code.– MeloMCR
Sep 19 '12 at 13:56
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
thanks! that was exactly what I was looking for!
– Dredok
Nov 14 '13 at 12:28
add a comment |
up vote
29
down vote
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;
}
1
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
add a comment |
up vote
29
down vote
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;
}
1
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
add a comment |
up vote
29
down vote
up vote
29
down vote
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;
}
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;
}
answered Jan 15 '12 at 1:56
ypnos
36.1k1374112
36.1k1374112
1
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
add a comment |
1
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
1
1
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
This answered a question I was about to post about converting floating-point grayscale values into a QImage...thank you!
– Nathan Moos
Feb 10 '12 at 19:17
add a comment |
up vote
23
down vote
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);
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
2
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded byimread
, or converted to appropriate type.
– Michal Kottman
Feb 18 '11 at 8:39
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
1
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
1
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
add a comment |
up vote
23
down vote
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);
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
2
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded byimread
, or converted to appropriate type.
– Michal Kottman
Feb 18 '11 at 8:39
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
1
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
1
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
add a comment |
up vote
23
down vote
up vote
23
down vote
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);
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);
edited Aug 15 '13 at 14:11
answered Feb 17 '11 at 23:46
Michal Kottman
13.6k23356
13.6k23356
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
2
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded byimread
, or converted to appropriate type.
– Michal Kottman
Feb 18 '11 at 8:39
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
1
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
1
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
add a comment |
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
2
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded byimread
, or converted to appropriate type.
– Michal Kottman
Feb 18 '11 at 8:39
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
1
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
1
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
This will not work in the general case. What if mat has >1 channels or data format is not RGB32?
– Hristo Hristov
Feb 18 '11 at 7:18
2
2
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded by
imread
, or converted to appropriate type.– Michal Kottman
Feb 18 '11 at 8:39
Well, yes, and it can also have multiple dimensions, or can have different 'step size'. I am expecting that Hien wants to display 'standard' cv::Mat, i.e. loaded by
imread
, or converted to appropriate type.– Michal Kottman
Feb 18 '11 at 8:39
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
@Michael Yes that is what I wanted. I'll try out your code once I have time to work on my project. =)
– Hien
Feb 20 '11 at 1:34
1
1
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
opencv uses the BGR channel order.
– etarion
Feb 20 '11 at 12:51
1
1
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
You can also convert the qimage to the right RGB order after its been created eg. qt_im_rgb = qt_im_bgr.rgbSwapped();
– ejectamenta
Mar 16 '17 at 8:39
add a comment |
up vote
3
down vote
Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR);
Mat dest;
cvtColor(opencv_image, dest,CV_BGR2RGB);
QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888);
This is what worked for me. I modified Michal Kottman's code above.
add a comment |
up vote
3
down vote
Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR);
Mat dest;
cvtColor(opencv_image, dest,CV_BGR2RGB);
QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888);
This is what worked for me. I modified Michal Kottman's code above.
add a comment |
up vote
3
down vote
up vote
3
down vote
Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR);
Mat dest;
cvtColor(opencv_image, dest,CV_BGR2RGB);
QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888);
This is what worked for me. I modified Michal Kottman's code above.
Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR);
Mat dest;
cvtColor(opencv_image, dest,CV_BGR2RGB);
QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888);
This is what worked for me. I modified Michal Kottman's code above.
answered Feb 5 '12 at 19:34
Mathai
4141421
4141421
add a comment |
add a comment |
up vote
2
down vote
cv::Mat has a conversion operator to IplImage, so if you have something that converts the IplImage to a QImage, just use that (or make the - probably minor - adjustments to take the cv::Mat directly, the memory layout is the same, it's "just" the header that is different.)
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
add a comment |
up vote
2
down vote
cv::Mat has a conversion operator to IplImage, so if you have something that converts the IplImage to a QImage, just use that (or make the - probably minor - adjustments to take the cv::Mat directly, the memory layout is the same, it's "just" the header that is different.)
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
add a comment |
up vote
2
down vote
up vote
2
down vote
cv::Mat has a conversion operator to IplImage, so if you have something that converts the IplImage to a QImage, just use that (or make the - probably minor - adjustments to take the cv::Mat directly, the memory layout is the same, it's "just" the header that is different.)
cv::Mat has a conversion operator to IplImage, so if you have something that converts the IplImage to a QImage, just use that (or make the - probably minor - adjustments to take the cv::Mat directly, the memory layout is the same, it's "just" the header that is different.)
answered Feb 17 '11 at 10:24
etarion
12.8k22961
12.8k22961
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
add a comment |
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
The project that I am working on requires me to print out the image onto the QtGui, but I will be working on the images in cv::Mat most of the time. The reason I am asking is that my program will do a lot of computation so I want to get rid of the overhead of converting cv::Mat to IplImage and then to qimage. This is my first image processing project so I don't really know much about the data that are in an image. I will learn about this soon enough once I dive more into the project. Anyway, if I can't find anything, then I'll follow your suggestion =)
– Hien
Feb 17 '11 at 10:46
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
Can you please share the code for IplImage -> QImage conversion? I am interested to make the needed adjustments to convert it to cv::Mat.
– Hristo Hristov
Feb 17 '11 at 11:04
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
@Hien: The overhead of the conversion cv::Mat to IplImage is, compared to all the other stuff you do when doing image processing, completely negligible. There is no copying of data involved.
– etarion
Feb 17 '11 at 11:57
add a comment |
up vote
2
down vote
I have the same problem as you too, so I develop four functions to alleviate my pain, they are
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);
QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);
cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);
cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
These functions can handle the images with 1, 3, 4 channels, every pixel must occupy one byte only(CV_8U->Format_Indexed8, CV_8UC3->QImage::Format_RGB888, CV_8UC4->QImage::Format_ARGB32), I do not deal with other types yet(QImage::Format_RGB16, QImage::Format_RGB666 and so on). The codes are located
at github.
The key concepts of **transform mat to Qimage ** are
/**
* @brief copy QImage into cv::Mat
*/
struct mat_to_qimage_cpy_policy
{
static QImage start(cv::Mat const &mat, QImage::Format format)
{
//The fourth parameters--mat.step is crucial, because
//opencv may do padding on every row, you need to tell
//the qimage how many bytes per row
//The last thing is if you want to copy the buffer of cv::Mat
//to the qimage, you need to call copy(), else the qimage
//will share the buffer of cv::Mat
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
};
struct mat_to_qimage_ref_policy
{
static QImage start(cv::Mat &mat, QImage::Format format)
{
//every thing are same as copy policy, but this one share
//the buffer of cv::Mat but not copy
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
};
The key concepts of transform cv::Mat to Qimage
are
/**
* @brief copy QImage into cv::Mat
*/
struct qimage_to_mat_cpy_policy
{
static cv::Mat start(QImage const &img, int format)
{
//same as convert mat to qimage, the fifth parameter bytesPerLine()
//indicate how many bytes per row
//If you want to copy the data you need to call clone(), else QImage
//cv::Mat will share the buffer
return cv::Mat(img.height(), img.width(), format,
const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
}
};
/**
* @brief make Qimage and cv::Mat share the same buffer, the resource
* of the cv::Mat must not deleted before the QImage finish
* the jobs.
*/
struct qimage_to_mat_ref_policy
{
static cv::Mat start(QImage &img, int format)
{
//same as copy policy, but this one will share the buffer
return cv::Mat(img.height(), img.width(), format,
img.bits(), img.bytesPerLine());
}
};
If would be good if some one can extend these functions and make them support more types, please inform me if there are any bugs.
add a comment |
up vote
2
down vote
I have the same problem as you too, so I develop four functions to alleviate my pain, they are
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);
QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);
cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);
cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
These functions can handle the images with 1, 3, 4 channels, every pixel must occupy one byte only(CV_8U->Format_Indexed8, CV_8UC3->QImage::Format_RGB888, CV_8UC4->QImage::Format_ARGB32), I do not deal with other types yet(QImage::Format_RGB16, QImage::Format_RGB666 and so on). The codes are located
at github.
The key concepts of **transform mat to Qimage ** are
/**
* @brief copy QImage into cv::Mat
*/
struct mat_to_qimage_cpy_policy
{
static QImage start(cv::Mat const &mat, QImage::Format format)
{
//The fourth parameters--mat.step is crucial, because
//opencv may do padding on every row, you need to tell
//the qimage how many bytes per row
//The last thing is if you want to copy the buffer of cv::Mat
//to the qimage, you need to call copy(), else the qimage
//will share the buffer of cv::Mat
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
};
struct mat_to_qimage_ref_policy
{
static QImage start(cv::Mat &mat, QImage::Format format)
{
//every thing are same as copy policy, but this one share
//the buffer of cv::Mat but not copy
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
};
The key concepts of transform cv::Mat to Qimage
are
/**
* @brief copy QImage into cv::Mat
*/
struct qimage_to_mat_cpy_policy
{
static cv::Mat start(QImage const &img, int format)
{
//same as convert mat to qimage, the fifth parameter bytesPerLine()
//indicate how many bytes per row
//If you want to copy the data you need to call clone(), else QImage
//cv::Mat will share the buffer
return cv::Mat(img.height(), img.width(), format,
const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
}
};
/**
* @brief make Qimage and cv::Mat share the same buffer, the resource
* of the cv::Mat must not deleted before the QImage finish
* the jobs.
*/
struct qimage_to_mat_ref_policy
{
static cv::Mat start(QImage &img, int format)
{
//same as copy policy, but this one will share the buffer
return cv::Mat(img.height(), img.width(), format,
img.bits(), img.bytesPerLine());
}
};
If would be good if some one can extend these functions and make them support more types, please inform me if there are any bugs.
add a comment |
up vote
2
down vote
up vote
2
down vote
I have the same problem as you too, so I develop four functions to alleviate my pain, they are
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);
QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);
cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);
cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
These functions can handle the images with 1, 3, 4 channels, every pixel must occupy one byte only(CV_8U->Format_Indexed8, CV_8UC3->QImage::Format_RGB888, CV_8UC4->QImage::Format_ARGB32), I do not deal with other types yet(QImage::Format_RGB16, QImage::Format_RGB666 and so on). The codes are located
at github.
The key concepts of **transform mat to Qimage ** are
/**
* @brief copy QImage into cv::Mat
*/
struct mat_to_qimage_cpy_policy
{
static QImage start(cv::Mat const &mat, QImage::Format format)
{
//The fourth parameters--mat.step is crucial, because
//opencv may do padding on every row, you need to tell
//the qimage how many bytes per row
//The last thing is if you want to copy the buffer of cv::Mat
//to the qimage, you need to call copy(), else the qimage
//will share the buffer of cv::Mat
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
};
struct mat_to_qimage_ref_policy
{
static QImage start(cv::Mat &mat, QImage::Format format)
{
//every thing are same as copy policy, but this one share
//the buffer of cv::Mat but not copy
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
};
The key concepts of transform cv::Mat to Qimage
are
/**
* @brief copy QImage into cv::Mat
*/
struct qimage_to_mat_cpy_policy
{
static cv::Mat start(QImage const &img, int format)
{
//same as convert mat to qimage, the fifth parameter bytesPerLine()
//indicate how many bytes per row
//If you want to copy the data you need to call clone(), else QImage
//cv::Mat will share the buffer
return cv::Mat(img.height(), img.width(), format,
const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
}
};
/**
* @brief make Qimage and cv::Mat share the same buffer, the resource
* of the cv::Mat must not deleted before the QImage finish
* the jobs.
*/
struct qimage_to_mat_ref_policy
{
static cv::Mat start(QImage &img, int format)
{
//same as copy policy, but this one will share the buffer
return cv::Mat(img.height(), img.width(), format,
img.bits(), img.bytesPerLine());
}
};
If would be good if some one can extend these functions and make them support more types, please inform me if there are any bugs.
I have the same problem as you too, so I develop four functions to alleviate my pain, they are
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);
QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);
cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);
cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
These functions can handle the images with 1, 3, 4 channels, every pixel must occupy one byte only(CV_8U->Format_Indexed8, CV_8UC3->QImage::Format_RGB888, CV_8UC4->QImage::Format_ARGB32), I do not deal with other types yet(QImage::Format_RGB16, QImage::Format_RGB666 and so on). The codes are located
at github.
The key concepts of **transform mat to Qimage ** are
/**
* @brief copy QImage into cv::Mat
*/
struct mat_to_qimage_cpy_policy
{
static QImage start(cv::Mat const &mat, QImage::Format format)
{
//The fourth parameters--mat.step is crucial, because
//opencv may do padding on every row, you need to tell
//the qimage how many bytes per row
//The last thing is if you want to copy the buffer of cv::Mat
//to the qimage, you need to call copy(), else the qimage
//will share the buffer of cv::Mat
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
};
struct mat_to_qimage_ref_policy
{
static QImage start(cv::Mat &mat, QImage::Format format)
{
//every thing are same as copy policy, but this one share
//the buffer of cv::Mat but not copy
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
};
The key concepts of transform cv::Mat to Qimage
are
/**
* @brief copy QImage into cv::Mat
*/
struct qimage_to_mat_cpy_policy
{
static cv::Mat start(QImage const &img, int format)
{
//same as convert mat to qimage, the fifth parameter bytesPerLine()
//indicate how many bytes per row
//If you want to copy the data you need to call clone(), else QImage
//cv::Mat will share the buffer
return cv::Mat(img.height(), img.width(), format,
const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
}
};
/**
* @brief make Qimage and cv::Mat share the same buffer, the resource
* of the cv::Mat must not deleted before the QImage finish
* the jobs.
*/
struct qimage_to_mat_ref_policy
{
static cv::Mat start(QImage &img, int format)
{
//same as copy policy, but this one will share the buffer
return cv::Mat(img.height(), img.width(), format,
img.bits(), img.bytesPerLine());
}
};
If would be good if some one can extend these functions and make them support more types, please inform me if there are any bugs.
answered Jul 27 '15 at 20:43
StereoMatching
2,62312550
2,62312550
add a comment |
add a comment |
up vote
1
down vote
This post shows how to convert a QImage
to OpenCV's IplImage
and vise-versa.
After that, if you need help to convert between IplImage*
to cv::Mat
:
// Assume data is stored by:
// IplImage* image;
cv::Mat mat(image, true); // Copies the data from image
cv::Mat mat(image, false); // Doesn't copy the data!
It's a hack, but will get the job done.
add a comment |
up vote
1
down vote
This post shows how to convert a QImage
to OpenCV's IplImage
and vise-versa.
After that, if you need help to convert between IplImage*
to cv::Mat
:
// Assume data is stored by:
// IplImage* image;
cv::Mat mat(image, true); // Copies the data from image
cv::Mat mat(image, false); // Doesn't copy the data!
It's a hack, but will get the job done.
add a comment |
up vote
1
down vote
up vote
1
down vote
This post shows how to convert a QImage
to OpenCV's IplImage
and vise-versa.
After that, if you need help to convert between IplImage*
to cv::Mat
:
// Assume data is stored by:
// IplImage* image;
cv::Mat mat(image, true); // Copies the data from image
cv::Mat mat(image, false); // Doesn't copy the data!
It's a hack, but will get the job done.
This post shows how to convert a QImage
to OpenCV's IplImage
and vise-versa.
After that, if you need help to convert between IplImage*
to cv::Mat
:
// Assume data is stored by:
// IplImage* image;
cv::Mat mat(image, true); // Copies the data from image
cv::Mat mat(image, false); // Doesn't copy the data!
It's a hack, but will get the job done.
answered Dec 8 '11 at 19:28
karlphillip
73.4k26183346
73.4k26183346
add a comment |
add a comment |
up vote
1
down vote
Use the static function convert16uc1 for the depth image:
QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
quint8 value = (quint8) ((*(pSource)) >> 8);
*(pDest++) = value; // B
*(pDest++) = value; // G
*(pDest++) = value; // R
*(pDest++) = 0; // Alpha
pSource++;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
quint8* pSource = source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
add a comment |
up vote
1
down vote
Use the static function convert16uc1 for the depth image:
QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
quint8 value = (quint8) ((*(pSource)) >> 8);
*(pDest++) = value; // B
*(pDest++) = value; // G
*(pDest++) = value; // R
*(pDest++) = 0; // Alpha
pSource++;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
quint8* pSource = source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
add a comment |
up vote
1
down vote
up vote
1
down vote
Use the static function convert16uc1 for the depth image:
QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
quint8 value = (quint8) ((*(pSource)) >> 8);
*(pDest++) = value; // B
*(pDest++) = value; // G
*(pDest++) = value; // R
*(pDest++) = 0; // Alpha
pSource++;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
quint8* pSource = source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
Use the static function convert16uc1 for the depth image:
QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
quint8 value = (quint8) ((*(pSource)) >> 8);
*(pDest++) = value; // B
*(pDest++) = value; // G
*(pDest++) = value; // R
*(pDest++) = 0; // Alpha
pSource++;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
quint8* pSource = source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
answered Jun 10 '13 at 13:42
D. Sangue
112
112
add a comment |
add a comment |
up vote
0
down vote
It might seem silly, but saving the image to a folder and then reading into a QImage object seemed to me the quickest way.
Mat x = imread("--.jpg");
imwrite("x.jpg", x);
QImage img("x.jpg");
add a comment |
up vote
0
down vote
It might seem silly, but saving the image to a folder and then reading into a QImage object seemed to me the quickest way.
Mat x = imread("--.jpg");
imwrite("x.jpg", x);
QImage img("x.jpg");
add a comment |
up vote
0
down vote
up vote
0
down vote
It might seem silly, but saving the image to a folder and then reading into a QImage object seemed to me the quickest way.
Mat x = imread("--.jpg");
imwrite("x.jpg", x);
QImage img("x.jpg");
It might seem silly, but saving the image to a folder and then reading into a QImage object seemed to me the quickest way.
Mat x = imread("--.jpg");
imwrite("x.jpg", x);
QImage img("x.jpg");
answered Jul 2 '17 at 22:06
Burak Mete
1116
1116
add a comment |
add a comment |
up vote
0
down vote
OpenCV loads images into a Mat
in Blue-Green-Red (BGR) format by default, while QImage
expects RGB. This means that if you convert a Mat
to QImage
, the blue and red channels will be swapped. To fix this, before constructing the QImage
, you need to change the BRG format of your Mat
to RGB, via the cvtColor
method using argument CV_BGR2RGB
, like so:
Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
Alternatively, use rgbSwapped()
on the QImage
QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());
add a comment |
up vote
0
down vote
OpenCV loads images into a Mat
in Blue-Green-Red (BGR) format by default, while QImage
expects RGB. This means that if you convert a Mat
to QImage
, the blue and red channels will be swapped. To fix this, before constructing the QImage
, you need to change the BRG format of your Mat
to RGB, via the cvtColor
method using argument CV_BGR2RGB
, like so:
Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
Alternatively, use rgbSwapped()
on the QImage
QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());
add a comment |
up vote
0
down vote
up vote
0
down vote
OpenCV loads images into a Mat
in Blue-Green-Red (BGR) format by default, while QImage
expects RGB. This means that if you convert a Mat
to QImage
, the blue and red channels will be swapped. To fix this, before constructing the QImage
, you need to change the BRG format of your Mat
to RGB, via the cvtColor
method using argument CV_BGR2RGB
, like so:
Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
Alternatively, use rgbSwapped()
on the QImage
QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());
OpenCV loads images into a Mat
in Blue-Green-Red (BGR) format by default, while QImage
expects RGB. This means that if you convert a Mat
to QImage
, the blue and red channels will be swapped. To fix this, before constructing the QImage
, you need to change the BRG format of your Mat
to RGB, via the cvtColor
method using argument CV_BGR2RGB
, like so:
Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
Alternatively, use rgbSwapped()
on the QImage
QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());
edited Nov 11 at 2:35
answered Nov 11 at 2:05
Gunnar Karlsson
26.2k105869
26.2k105869
add a comment |
add a comment |
up vote
-1
down vote
This did the trick for me. It's a little dodgy, has terrible performance (as pointed out in the comments), but works with all color formats I have thrown at it so far, and it is also very simple to do.
The procedure is as follows:
cv::Mat image = //...some image you want to display
// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);
// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
Done!
If you, say, want to display it in a QLabel, then continue with:
// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));
I personally use this for a simple image editor.
3
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
add a comment |
up vote
-1
down vote
This did the trick for me. It's a little dodgy, has terrible performance (as pointed out in the comments), but works with all color formats I have thrown at it so far, and it is also very simple to do.
The procedure is as follows:
cv::Mat image = //...some image you want to display
// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);
// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
Done!
If you, say, want to display it in a QLabel, then continue with:
// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));
I personally use this for a simple image editor.
3
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
add a comment |
up vote
-1
down vote
up vote
-1
down vote
This did the trick for me. It's a little dodgy, has terrible performance (as pointed out in the comments), but works with all color formats I have thrown at it so far, and it is also very simple to do.
The procedure is as follows:
cv::Mat image = //...some image you want to display
// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);
// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
Done!
If you, say, want to display it in a QLabel, then continue with:
// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));
I personally use this for a simple image editor.
This did the trick for me. It's a little dodgy, has terrible performance (as pointed out in the comments), but works with all color formats I have thrown at it so far, and it is also very simple to do.
The procedure is as follows:
cv::Mat image = //...some image you want to display
// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);
// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
Done!
If you, say, want to display it in a QLabel, then continue with:
// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));
I personally use this for a simple image editor.
edited Nov 19 '15 at 8:27
answered Oct 4 '13 at 10:01
Tormod Haugene
1,51511837
1,51511837
3
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
add a comment |
3
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
3
3
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
This has a terrible performance.
– AxeEffect
Jun 14 '15 at 11:26
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
@AxeEffect This is certainly not a high performing solution, considering you have to do read/write operation towards the HDD. For some usages, though, that doesn't really matter. :-)
– Tormod Haugene
Jun 14 '15 at 19:40
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5026965%2fhow-to-convert-an-opencv-cvmat-to-qimage%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It will be useful if such code exists, but there are some issues in writing it: cv::Mat support more data types than QImage, cv::Mat supports multiple channels, should the data be copied or wrapped around the original data...
– Hristo Hristov
Feb 17 '11 at 9:36