2016-11-22 111 views
3

我已經開始學習Qt,並試圖製作一個簡單的視頻播放器,它將加載視頻並播放它。它工作得很好。現在添加了閾值功能。閾值將從spinBox中獲得。 代碼的寫入方式是除了值爲0(顯示正常視頻)之外,閾值操作將在spinBox中以值的形式完成。 所以這是我的同一個函數:如何將灰度/二進制Mat轉換爲QImage?

void Player::run() 
{ 

while(!stop) 
{ 

    if(!capture.read(frame)) 
     stop = true; 
    // convert RGB to gray 
    if(frame.channels() == 3) 
    { 
     if(thresh == 0) 
     { 
      cvtColor(frame, RGBframe, CV_BGR2RGB); 
      img = QImage((const unsigned char*)(RGBframe.data), 
          RGBframe.cols,RGBframe.rows,QImage::Format_RGB888); 

     } 
     else 
     { 
      Mat temp; 
      cvtColor(frame, temp, CV_BGR2GRAY); 
      threshold(temp, binary, thresh, 255, 0); 
      img = QImage((const unsigned char*)(binary.data), 
           binary.cols, binary.rows, QImage::Format_Indexed8); 




      bool save = img.save("/home/user/binary.png"); 

      cout<<"threshold value = "<<thresh<<endl; 

      //imshow("Binary", binary); 
     } 
    } 
    else 
    { 
     if(thresh == 0) // original Image 
     { 
      img = QImage((const unsigned char*)(frame.data), 
          frame.cols,frame.rows,QImage::Format_Indexed8); 

     } 
     else // convert to Binary Image 
     { 

      threshold(frame, binary, thresh, 255, 0); 

      img = QImage((const unsigned char*)(binary.data), 
           binary.cols, binary.rows, QImage::Format_Indexed8); 
     } 




    } 

    emit processedImage(img); 
    this->msleep(delay); 
} 
} 

爲SPINBOX值等於0,則運行正常,但當SPINBOX值增加我只得到黑屏。我試過imshow(cv:: Mat binary),它顯示正確的二進制圖像,但當我嘗試保存QImage img時,它是一些隨機的黑白像素(儘管原始幀的大小相同)。

+1

看來你缺少一個colorTable。在while循環之前添加:'QVector sColorTable(256);對於(int i = 0; i <256; ++ i){sColorTable [i] = qRgb(i,i,i);}',並且在從二進制文件創建'QImage'後,添加'img.setColorTable sColorTable);' – Miki

+0

彩色圖像輸入案例還是灰度圖像輸入案例? afair灰度不是在Qt中索引的類型,afair我不得不使用顏色表。 – Micka

回答

2

看起來你錯過了索引圖像的顏色表。您需要添加一個顏色表(前while循環):

QVector<QRgb> sColorTable(256); 
for (int i = 0; i < 256; ++i){ sColorTable[i] = qRgb(i, i, i); } 

,你從二進制Mat創建QImage後,你需要添加

img.setColorTable(sColorTable); 

或者,正如@KubaOber指出,從Qt的5.5,你也可以使用格式QImage::Format_Grayscale8

// From Qt 5.5 
QImage image(inMat.data, inMat.cols, inMat.rows, 
      static_cast<int>(inMat.step), 
      QImage::Format_Grayscale8); 

一般情況下,你可以用所有MatQImage函數中的轉換。下面是錯誤更正已更新版本cvMatToQImage最初發現here

然後,您可以從您的代碼中刪除所有轉換爲QImage,並改用此函數。

QImage cvMatToQImage(const cv::Mat &inMat) 
{ 
    switch (inMat.type()) 
    { 
     // 8-bit, 4 channel 
    case CV_8UC4: 
    { 
     QImage image(inMat.data, 
      inMat.cols, inMat.rows, 
      static_cast<int>(inMat.step), 
      QImage::Format_ARGB32); 

     return image; 
    } 

    // 8-bit, 3 channel 
    case CV_8UC3: 
    { 
     QImage image(inMat.data, 
      inMat.cols, inMat.rows, 
      static_cast<int>(inMat.step), 
      QImage::Format_RGB888); 

     return image.rgbSwapped(); 
    } 

    // 8-bit, 1 channel 
    case CV_8UC1: 
    { 
#if QT_VERSION >= 0x050500 

     // From Qt 5.5 
     QImage image(inMat.data, inMat.cols, inMat.rows, 
        static_cast<int>(inMat.step), 
        QImage::Format_Grayscale8); 
#else 
     static QVector<QRgb> sColorTable; 

     // only create our color table the first time 
     if (sColorTable.isEmpty()) 
     { 
      sColorTable.resize(256); 
      for (int i = 0; i < 256; ++i) 
      { 
       sColorTable[i] = qRgb(i, i, i); 
      } 
     } 

     QImage image(inMat.data, 
      inMat.cols, inMat.rows, 
      static_cast<int>(inMat.step), 
      QImage::Format_Indexed8); 

     image.setColorTable(sColorTable); 
#endif 
    } 

    default: 
     qWarning() << "cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type(); 
     break; 
    } 

    return QImage(); 
} 
+0

感謝這個附加功能@Miki –

+1

@ Optimus1072很高興幫助。我更新了問題的標題以更好地反映問題並幫助其他人找到此解決方案 – Miki

+0

對於灰度圖像,我們還需要colorMap嗎? –