天天看點

VS+QT+OpenCV圖像處理輸出

在使用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

  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.         qDebug() << "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.         qDebug() << "ERROR: Mat could not be converted to QImage.";    
  44.         return QImage();    
  45.     }    
  46. }

[cpp]  view plain  copy

  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.         mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());  
  10.         break;  
  11.     case QImage::Format_RGB888:  
  12.         mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());  
  13.         cv::cvtColor(mat, mat, CV_BGR2RGB);  
  14.         break;  
  15.     case QImage::Format_Indexed8:  
  16.         mat = cv::Mat(image.height(), image.width(), CV_8UC1, (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的操作

本文代碼片段來源:http://blog.csdn.net/dancing_night/article/details/51545524,如有侵犯,請聯系本人好及時删除。