在使用VS+QT+OpenCV做图像处理的过程中,对OpenCV中的Mat类型的数据格式一直很头疼CV_8UC4,CV_32F等等格式的输出如果是在使用namewindow+imshow的组合进行弹窗输出时确实是没有什么大问题,但是当需要把图片转成QImage输出到控件上时就会出大问题了,因为不同图片格式的Mat在转成QImage时需要使用不同的参数。
但是好在Mat类型在自身的不同格式间转换时没有什么阻碍的。所以就此整理出以下Mat类型输出到QT控件的方法。
一、输出灰度图像,输出灰度图像在格式转换前后通常来说不会有太大的影响,仅有的影响也就只有因为QImage可能会只显示图片的左上角某一部分(长三分之一,宽三分之一),在我看来应该是图像中每个像素数据所占的位数不一样导致的。所以通常只需要在转成QImage前把图片使用mat.convertTo(mat,CV_8UC3){也可以用其他格式}转换格式后再转成QImage(转成QImage的方法在下面会给出)。
二、输出RGB图,输出RGB图在通常时和输出灰度图是一样的(这个通常情况指的是读取的是RGB图,输出这个读取的RGB图),但是如果对RGB图进行了三个通道的拆分后,对RGB通道分别处理以后再重新合成RGB图像的话(使用vector<Mat> vmat读取B G R三个通道的数据并分别处理,最后使用merge(vmat,mat)组成输出的图像),需要在merge后再次使用convertTO转变mat的格式,然后才能统一输出,至于转成什么格式,推荐是CV_8UC1,CV_8UC3,CV_8UC4,原因的话,因为本人对QImage的数据格式不了解,只能参照其他博主的QImage和Mat类型的格式转换方法,在之前搜索的资料中看到过两个博主的代码是可用的,根据自己的使用体验推荐下面这段代码
[cpp] view plain copy
[cpp] view plain copy
1. QImage MatToQImage(const cv::Mat& mat)
2. {
3. // 8-bits unsigned, NO. OF CHANNELS = 1
4. if(mat.type() == CV_8UC1)
5. {
6. QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
7. // Set the color table (used to translate colour indexes to qRgb values)
8. image.setColorCount(256);
9. for(int i = 0; i < 256; i++)
10. {
11. image.setColor(i, qRgb(i, i, i));
12. }
13. // Copy input Mat
14. uchar *pSrc = mat.data;
15. for(int row = 0; row < mat.rows; row ++)
16. {
17. uchar *pDest = image.scanLine(row);
18. memcpy(pDest, pSrc, mat.cols);
19. pSrc += mat.step;
20. }
21. return image;
22. }
23. // 8-bits unsigned, NO. OF CHANNELS = 3
24. else if(mat.type() == CV_8UC3)
25. {
26. // Copy input Mat
27. const uchar *pSrc = (const uchar*)mat.data;
28. // Create QImage with same dimensions as input Mat
29. QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
30. return image.rgbSwapped();
31. }
32. else if(mat.type() == CV_8UC4)
33. {
34. "CV_8UC4";
35. // Copy input Mat
36. const uchar *pSrc = (const uchar*)mat.data;
37. // Create QImage with same dimensions as input Mat
38. QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
39. return image.copy();
40. }
41. else
42. {
43. "ERROR: Mat could not be converted to QImage.";
44. return QImage();
45. }
46. }
1. cv::Mat QImageToMat(QImage image)
2. {
3. cv::Mat mat;
4. switch (image.format())
5. {
6. case QImage::Format_ARGB32:
7. case QImage::Format_RGB32:
8. case QImage::Format_ARGB32_Premultiplied:
9. void*)image.constBits(), image.bytesPerLine());
10. break;
11. case QImage::Format_RGB888:
12. void*)image.constBits(), image.bytesPerLine());
13. cv::cvtColor(mat, mat, CV_BGR2RGB);
14. break;
15. case QImage::Format_Indexed8:
16. void*)image.constBits(), image.bytesPerLine());
17. break;
18. }
19. return mat;
20. }
在图片格式转换完成后,使用
ui.QLabel->setPixmap(QPixmap::fromImage(QImage));
ui.QLabel->resize(ui.QLabel->pixmap()->size());
完成QImage输出到QLabel的操作