我的OpenCV學習筆記(13):計算長條圖,利用尋找表展開長條圖,長條圖均衡

來源:互聯網
上載者:User

一些標頭檔:

#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <iostream>using namespace std;using namespace cv;

 

首先建立一個類:

class Histogram1D{private://長條圖的點數int histSize[1];//長條圖的範圍float hranges[2];//指向該範圍的指標const float* ranges[1];//通道int channels[1];public://建構函式Histogram1D(){ histSize[0] = 256; hranges[0] = 0.0; hranges[1] = 255.0; ranges[0] = hranges; channels[0] = 0;}

 

在OpenCV中,使用calcHist計算長條圖

Mat getHistogram(const Mat &image){Mat hist;//計算長條圖函數//參數為:源映像(序列)地址,輸入映像的個數,通道數,掩碼,輸出結果,長條圖維數,每一維的大小,每一維的取值範圍calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);return hist;}

但是,返回的結果並不是我們希望的“長條圖”,hist只是記錄了每個bin下的像素個數。我們需要自己利用line函數畫圖:

Mat getHistogramImage(const Mat &image){//首先計算長條圖Mat hist = getHistogram(image);//擷取最大值和最小值double maxVal = 0;double minVal = 0;//minMaxLoc用來獲得最大值和最小值,後面兩個參數為最小值和最大值的位置,0代表不需要擷取minMaxLoc(hist,&minVal,&maxVal,0,0);//展示長條圖的畫板:底色為白色Mat histImg(histSize[0],histSize[0],CV_8U,Scalar(255));//將最高點設為bin總數的90%int hpt = static_cast<int>(0.9*histSize[0]);//為每一個bin畫一條線for(int h = 0; h < histSize[0];h++){float binVal = hist.at<float>(h);int intensity = static_cast<int>(binVal*hpt/maxVal);//int intensity = static_cast<int>(binVal);line(histImg,Point(h,histSize[0]),Point(h,histSize[0]-intensity),Scalar::all(0));}return histImg;}

函數中對亮度進行了“壓縮”,主要目的是讓長條圖能夠更好的顯示在畫板上。

尋找表,就是一個一對一或者多對一函數,指定了一個亮度經過尋找表以後變成另外一個像素。在OpenCV中,使用LUT函數來實現

Mat applyLookUp(const Mat& image,const Mat& lookup){Mat result;LUT(image,lookup,result);return result;}

 

而變化的具體內容,依賴於你自己定義的尋找表,比如,如果你想讓尋找表的結果為當前映像的翻轉,可以在main函數中定義尋找表為:

//用尋找表翻轉映像灰階int dim(256);Mat lut(1,&dim,CV_8U);for(int i = 0; i < 256; i++){lut.at<uchar>(i) = 255-i;}imshow("灰階翻轉後的映像",h.applyLookUp(image,lut));

當你想讓映像經過尋找表以後長條圖展開,變得效果好一點,可以這樣:

將個數低於指定數目(預設為0)的bin捨去,剩下的最小值變為0,最大值變為255,中間的部分線性展開:

Mat strech(const Mat &image,int minValue = 0){//首先計算長條圖Mat hist = getHistogram(image);//左邊入口int imin = 0;for(;imin< histSize[0];imin++){cout<<hist.at<float>(imin)<<endl;if(hist.at<float>(imin) > minValue)break;}//右邊入口int imax = histSize[0]-1;for(;imax >= 0; imax--){if(hist.at<float>(imax) > minValue)break;}//建立尋找表int dim(256);Mat lookup(1,&dim,CV_8U);for(int i = 0; i < 256; i++){if(i < imin){lookup.at<uchar>(i) = 0;}else if(i > imax){lookup.at<uchar>(i) = 255;}else{lookup.at<uchar>(i) = static_cast<uchar>(255.0*(i-imin)/(imax-imin)+0.5);}}Mat result;result = applyLookUp(image,lookup);return result;}

當然,這樣的效果還不是最好的,最好的均衡應該使得長條圖非常平緩,每個bin中的數目差不多,在OpenCV中,使用equalizeHist函數可以實現長條圖均衡功能:

Mat equalize(const Mat &image){Mat result;equalizeHist(image,result);return result;}

有了上面定義的類,我們main函數就變得簡單多了:

#include "histogram.h"int main(){//以灰階方式讀取映像Mat image = imread("D:/picture/images/group.jpg",0);imshow("源灰階映像",image);if (!image.data)return -1;Histogram1D h;imshow("長條圖",h.getHistogramImage(image));//用尋找表翻轉映像灰階int dim(256);Mat lut(1,&dim,CV_8U);for(int i = 0; i < 256; i++){lut.at<uchar>(i) = 255-i;}imshow("灰階翻轉後的映像",h.applyLookUp(image,lut));//用尋找表展開映像灰階值//忽略那些個數少於100個像素的binMat strech = h.strech(image,100);imshow("展開後的映像",strech);imshow("展開後的長條圖",h.getHistogramImage(strech));//映像均衡Mat afterEqualize = h.equalize(image);imshow("均衡後的解果",afterEqualize);imshow("均衡後的長條圖",h.getHistogramImage(afterEqualize));waitKey(0);return 0;}

由於畫的圖比較多,這裡就不貼結果了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.