2012-09-09 56 views
20

在OpenCV的C++接口中,似乎很容易檢查圖像的類型。如果你有一個圖像cv::Mat img = cv::imread("someImage.xyz"),你只需要int theType = img.type()獲取OpenCV圖像類型的枚舉名稱(例如CV_32FC1)?

但是,正如您所期望的那樣,調用img.type()只是給出一個整數,而不是枚舉名稱(例如CV_32FC1)。

如果我知道OpenCV枚舉的整數值,是否有簡便的方法可以打印出枚舉名稱(例如CV_32FC1)?

+0

對於那些碰巧熟悉CUDA的人,我正在尋找的OpenCV函數有點像CUDA中的'cudaGetErrorString(int)'函數。 – solvingPuzzles

回答

30

據我所知,OpenCV中不存在這樣的函數。

我想你會更好地寫自己的功能來獲得這些。很多開關盒,但我想它是做這個工作的。枚舉可以找到here

編輯:

這是你可以用它來提取類型。我猜測可能會有一種更有效的方法,但現在我無法將其包圍。

std::string getImageType(int number) 
{ 
    // find type 
    int imgTypeInt = number%8; 
    std::string imgTypeString; 

    switch (imgTypeInt) 
    { 
     case 0: 
      imgTypeString = "8U"; 
      break; 
     case 1: 
      imgTypeString = "8S"; 
      break; 
     case 2: 
      imgTypeString = "16U"; 
      break; 
     case 3: 
      imgTypeString = "16S"; 
      break; 
     case 4: 
      imgTypeString = "32S"; 
      break; 
     case 5: 
      imgTypeString = "32F"; 
      break; 
     case 6: 
      imgTypeString = "64F"; 
      break; 
     default: 
      break; 
    } 

    // find channel 
    int channel = (number/8) + 1; 

    std::stringstream type; 
    type<<"CV_"<<imgTypeString<<"C"<<channel; 

    return type.str(); 
} 
+0

好的想法。我遵循你的建議,並寫了一些代碼來做到這一點。請參閱下面的答案。 – solvingPuzzles

+0

而不是使用整數(當你在你的特定版本上檢查它們時是正確的),你應該使用枚舉本身。 'case 8U:str =「8U」'那麼如果枚舉在不同的版本中發生變化,那麼你一定會弄錯它們。 – Octopus

19

繼@鮑勃的建議,我寫我自己的函數來解決這個問題。它是:

// take number image type number (from cv::Mat.type()), get OpenCV's enum string. 
string getImgType(int imgTypeInt) 
{ 
    int numImgTypes = 35; // 7 base types, with five channel options each (none or C1, ..., C4) 

    int enum_ints[] =  {CV_8U, CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, 
          CV_8S, CV_8SC1, CV_8SC2, CV_8SC3, CV_8SC4, 
          CV_16U, CV_16UC1, CV_16UC2, CV_16UC3, CV_16UC4, 
          CV_16S, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, 
          CV_32S, CV_32SC1, CV_32SC2, CV_32SC3, CV_32SC4, 
          CV_32F, CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4, 
          CV_64F, CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4}; 

    string enum_strings[] = {"CV_8U", "CV_8UC1", "CV_8UC2", "CV_8UC3", "CV_8UC4", 
          "CV_8S", "CV_8SC1", "CV_8SC2", "CV_8SC3", "CV_8SC4", 
          "CV_16U", "CV_16UC1", "CV_16UC2", "CV_16UC3", "CV_16UC4", 
          "CV_16S", "CV_16SC1", "CV_16SC2", "CV_16SC3", "CV_16SC4", 
          "CV_32S", "CV_32SC1", "CV_32SC2", "CV_32SC3", "CV_32SC4", 
          "CV_32F", "CV_32FC1", "CV_32FC2", "CV_32FC3", "CV_32FC4", 
          "CV_64F", "CV_64FC1", "CV_64FC2", "CV_64FC3", "CV_64FC4"}; 

    for(int i=0; i<numImgTypes; i++) 
    { 
     if(imgTypeInt == enum_ints[i]) return enum_strings[i]; 
    } 
    return "unknown image type"; 
} 

我忘了在查找表中包含任何OpenCV圖像類型嗎?

+0

你必須注意兩點。首先,沒有任何情況下你有零通道,總是至少有一個通道,這實際上意味着CV_8U = CV_8UC1等。第二,你可以有最多CV_CN_MAX通道,根據2.4.2文檔設置爲512,所以你以這種方式將自己限制在4個頻道。我寫了一些東西,看看我的編輯,只是確保測試它,因爲我沒有編譯它。 – Sassa

+0

@Bob你確定5至512像素的枚舉被實現了嗎?編譯器說CV_8UC5沒有定義。 – solvingPuzzles

+0

它們不是#defined,但它們是使用CV_MAKETYPE派生的,例如CV_MAKETYPE(CV_32F,5);當然,如果你不打算使用這麼多的頻道,你可以使用你的功能,只是刪除CV_8U等,因爲他們返回的結果與CV_8UC1等 – Sassa