【從零學習OpenCV 4】LUT查找表

  • 2019 年 11 月 30 日
  • 筆記

經過幾個月的努力,小白終於完成了市面上第一本OpenCV 4入門書籍《從零學習OpenCV 4》。為了更讓小夥伴更早的了解最新版的OpenCV 4,小白與出版社溝通,提前在公眾號上連載部分內容,請持續關注小白。

前面介紹的閾值比較方法中只有一個閾值,如果需要與多個閾值進行比較,就需要用到顯示查找表(Look-Up-Table,LUT)。LUT查找表簡單來說就是一個像素灰度值的映射表,它以像素灰度值作為索引,以灰度值映射後的數值作為表中的內容。例如我們有一個長度為5的存放字元的數組,LUT查找表就是通過這個數組將0映射成a,將1映射成b,依次類推,其映射關係為。在OpenCV 4中提供了LUT()函數用於實現影像像素灰度值的LUT查找表功能,在程式碼清單3-20中給出了該函數的原型。

程式碼清單3-20 LUT()函數原型  1.  void cv::LUT(InputArray src,  2.                  InputArray lut,  3.                  OutputArray dst  4.                 )
  • src:輸入影像矩陣,其數據類型只能是CV_8U。
  • lut:256個像素灰度值的查找表,單通道或者與src通道數相同。
  • dst:輸出影像矩陣,其尺寸與src相同,數據類型與lut相同。

該函數的第一個輸入參數要求的數據類型必須是CV_8U類型,但是可以是多通道的影像矩陣。第二個參數根據其參數說明可以知道輸入量是一個1×256的矩陣,其中存放著每個像素灰度值映射後的數值,其形式如圖3-17所示。如果第二個參數是單通道,則輸入變數中的每個通道都按照一個LUT查找表進行映射;如果第二個參數是多通道,則輸入變數中的第i個通道按照第二個參數的第i個通道LUT查找表進行映射。與之前的函數不同,函數輸出影像的數據類型不與原影像的數據類型保持一致,而是和LUT查找表的數據類型保持一致,這是因為將原灰度值映射到新的空間中,因此需要與新空間中的數據類型保持一致。

圖3-17 LUT查找表設置示例

為了體會LUT查找表處理影像後的效果,在程式碼清單3-21中給出通過LUT()函數將灰度影像和彩色影像分別處理的示常式序,程式中分別應用單通道和三通道的查找表對彩色影像進行映射,最終結果在圖3-18中給出。

程式碼清單3-21 myLUT.cpp對影像進行查找表映射  1.  #include <opencv2opencv.hpp>  2.  #include <iostream>  3.  4.  using namespace std;  5.  using namespace cv;  6.  7.  int main(int agrc, char** agrv)  8. {  9.    //LUT查找表第一層  10.    uchar lutFirst[256];  11.    for (int i = 0; i<256; i++)  12.    {  13.      if (i <= 100)  14.        lutFirst[i] = 0;  15.      if (i > 100 && i <= 200)  16.        lutFirst[i] = 100;  17.      if (i > 200)  18.        lutFirst[i] = 255;  19.    }  20.    Mat lutOne(1, 256, CV_8UC1, lutFirst);  21.  22.    //LUT查找表第二層  23.    uchar lutSecond[256];  24.    for (int i = 0; i<256; i++)  25.    {  26.      if (i <= 100)  27.        lutSecond[i] = 0;  28.      if (i > 100 && i <= 150)  29.        lutSecond[i] = 100;  30.      if (i > 150 && i <= 200)  31.        lutSecond[i] = 150;  32.      if (i > 200)  33.        lutSecond[i] = 255;  34.    }  35.    Mat lutTwo(1, 256, CV_8UC1, lutSecond);  36.  37.    //LUT查找表第三層  38.    uchar lutThird[256];  39.    for (int i = 0; i<256; i++)  40.    {  41.      if (i <= 100)  42.        lutThird[i] = 100;  43.      if (i > 100 && i <= 200)  44.        lutThird[i] = 200;  45.      if (i > 200)  46.        lutThird[i] = 255;  47.    }  48.    Mat lutThree(1, 256, CV_8UC1, lutThird);  49.  50.    //擁有三通道的LUT查找表矩陣  51.    vector<Mat> mergeMats;  52.    mergeMats.push_back(lutOne);  53.    mergeMats.push_back(lutTwo);  54.    mergeMats.push_back(lutThree);  55.    Mat LutTree;  56.    merge(mergeMats, LutTree);  57.  58.    //計算影像的查找表  59.    Mat img = imread("lena.png");  60.    if (img.empty())  61.    {  62.      cout << "請確認影像文件名稱是否正確" << endl;  63.      return -1;  64.    }  65.  66.    Mat gray, out0, out1, out2;  67.    cvtColor(img, gray, COLOR_BGR2GRAY);  68.    LUT(gray, lutOne, out0);  69.    LUT(img, lutOne, out1);  70.    LUT(img, LutTree, out2);  71.    imshow("out0", out0);  72.    imshow("out1", out1);  73.    imshow("out2", out2);  74.    waitKey(0);  75.    return 0;  76.  }

圖3-18 myLUT.cpp程式運行結果