【從零學習OpenCV 4】直方圖均衡化

  • 2019 年 12 月 24 日
  • 筆記

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

如果一個影像的直方圖都集中在一個區域,則整體影像的對比度比較小,不便於影像中紋理的識別。例如相鄰的兩個像素灰度值如果分別是120和121,僅憑肉眼是如法區別出來的。同時,如果影像中所有的像素灰度值都集中在100到150之間,則整個影像想會給人一種模糊的感覺,看不清圖中的內容。如果通過映射關係,將影像中灰度值的範圍擴大,增加原來兩個灰度值之間的差值,就可以提高影像的對比度,進而將影像中的紋理突出顯現出來,這個過程稱為影像直方圖均衡化。

在OpenCV 4中提供了equalizeHist()函數用於將影像的直方圖均衡化,該函數的函數原型在程式碼清單4-7中給出。

程式碼清單4-7 equalizeHist()函數原型  1.  void cv::equalizeHist(InputArray src,  2.                             OutputArray dst  3.                             )
  • src:需要直方圖均衡化的CV_8UC1影像。
  • dst:直方圖均衡化後的輸出影像,與src具有相同尺寸和數據類型。

該函數形式比較簡單,但是需要注意該函數只能對單通道的灰度圖進行直方圖均衡化。對影像的均衡化示常式序在程式碼清單4-8中給出,程式中我們將一張影像灰度值偏暗的影像進行均衡化,通過結果可以發現經過均衡化後的影像對比度明顯增加,可以看清楚原來看不清的紋理。通過繪製原圖和均衡化後的影像的直方圖可以發現,經過均衡化後的影像直方圖分布更加均勻。

程式碼清單4-8 myEqualizeHist.cpp直方圖均衡化實現  4.  #include <opencv2opencv.hpp>  5.  #include <iostream>  6.  7.  using namespace cv;  8.  using namespace std;  9.  10.  void drawHist(Mat &hist, int type, string name)  //歸一化並繪製直方圖函數  11. {  12.    int hist_w = 512;  13.    int hist_h = 400;  14.    int width = 2;  15.    Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);  16.    normalize(hist, hist, 1, 0, type, -1, Mat());  17.    for (int i = 1; i <= hist.rows; i++)  18.    {  19.      rectangle(histImage, Point(width*(i - 1), hist_h - 1),  20.        Point(width*i - 1, hist_h - cvRound(hist_h*hist.at<float>(i - 1)) - 1),  21.        Scalar(255, 255, 255), -1);  22.    }  23.    imshow(name, histImage);  24.  }  25.  //主函數  26.  int main()  27. {  28.    Mat img = imread("gearwheel.jpg");  29.    if (img.empty())  30.    {  31.      cout << "請確認影像文件名稱是否正確" << endl;  32.      return -1;  33.    }  34.    Mat gray, hist, hist2;  35.    cvtColor(img, gray, COLOR_BGR2GRAY);  36.    Mat equalImg;  37.    equalizeHist(gray, equalImg); //將影像直方圖均衡化  38.    const int channels[1] = { 0 };  39.    float inRanges[2] = { 0,255 };  40.    const float* ranges[1] = { inRanges };  41.    const int bins[1] = { 256 };  42.    calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);  43.    calcHist(&equalImg, 1, channels, Mat(), hist2, 1, bins, ranges);  44.    drawHist(hist, NORM_INF, "hist");  45.    drawHist(hist2, NORM_INF, "hist2");  46.    imshow("原圖", gray);  47.    imshow("均衡化後的影像", equalImg);  48.    waitKey(0);  49.    return 0;  50.  }

圖4-6 myEqualizeHist.cpp程式運行結果