在使用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的操作