OpenCV3入門(十一)影象直方圖
1、直方圖的概念
灰度直方圖是灰度級的函式,描述的是影象中具有該灰度級的像元的個數。確定影象畫素的灰度值範圍,以適當的灰度間隔為單位將其劃分為若干等級,以橫軸表示灰度級,以縱軸表示每一灰度級具有的畫素數或該畫素佔總像元數的比例值,做出的條形統計圖即為灰度直方圖。灰度直方圖:橫座標是灰度,縱座標是該灰度在影象中出現的次數。
影象直方圖可以表示影象中亮度分佈,能借助直方圖瞭解需要如何調整亮度分佈,直方圖中左側表示黑色、較暗的區域,右側表示白色、較亮的區域。計算機視覺領域常藉助直方圖來實現影象的二值化。
2、OpenCV直方圖
OpenCV使用calcHist函式實現直方圖計算,函式原型如下圖。
CV_EXPORTS void calcHist( const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform = true, bool accumulate = false );
引數詳解:
onst Mat* images:輸入影象組
int nimages:輸入影象的個數
const int* channels:需要統計直方圖的第幾通道
InputArray mask:掩膜,計算掩膜內的直方圖
OutputArray hist:輸出的直方圖的陣列
int dims:直方圖的維度,需要統計直方圖通道的個數
const int* histSize:指的是直方圖分成多少個區間,就是 bin的個數
const float** ranges: 統計畫素值的區間,每個維度數值的取值範圍
bool uniform=true:是否對得到的直方圖陣列進行歸一化處理
bool accumulate=false:在多個影象時,是否累計計算畫素值得個數
測試程式碼如下:
Mat src = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\img1.bmp"); imshow("原圖", src); MatND dstHist; int dims = 1; float hranges[] = { 0,255 }; const float *ranges[]= { hranges }; int size = 256; int channels = 0; calcHist(&src, 1, &channels, Mat(), dstHist, dims, &size, ranges); double maxVal = 0; double minVal = 0; cv::minMaxLoc(dstHist, &minVal, &maxVal, 0, 0); Mat histImg(size, size, CV_8U, cv::Scalar(0)); int hpt = static_cast<int>(0.9*size); for (int h = 0; h < 256; h++) { float binVal = dstHist.at<float>(h); int intensity = static_cast<int>(binVal * hpt / maxVal); cv::line(histImg, Point(h, size-1), Point(h+1, size-1 - intensity), Scalar::all(255)); } imshow("直方圖", histImg); waitKey(0);
輸出結果為:
如果是彩色影象,則可以計算RGB通道各自的直方圖。
測試程式碼如下:
Mat src = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic5.bmp"); imshow("原圖", src); int histsize = 256; float range[] = { 0,256 }; const float*histRanges = { range }; vector<Mat>bgr_planes; split(src, bgr_planes); Mat b_hist, g_hist, r_hist; calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histsize, &histRanges, true, false); Mat histImg = Mat::zeros(256, 256*3, CV_8UC3); for (int h = 0; h < 256; h++) { float binVal_r = r_hist.at<float>(h); float binVal_g = g_hist.at<float>(h); float binVal_b = b_hist.at<float>(h); rectangle(histImg, Point(h, 256 - 1), Point(h + 1, 256 - binVal_r), Scalar(255, 0, 0)); rectangle(histImg, Point(h+255, 256 - 1), Point(h +255+ 1, 256 - binVal_g), Scalar(0, 255, 0)); rectangle(histImg, Point(h+510, 256 - 1), Point(h + 510+ 1, 256 - binVal_b), Scalar(0, 0, 255)); } imshow("直方圖", histImg);
輸出結果為:
3、直方圖均衡化
直方圖均衡化即灰度均衡化,通過灰度對映,使輸入影象的灰度轉換為在每一級灰度上都有近似相同的點數分佈,這樣輸出的直方圖就是均勻的,影象獲得較高的對比度和較大的動態範圍。直方圖均衡化對影象進行非線性拉伸,重新分配影象畫素值,使一定灰度範圍內的畫素數量大致相同。使用直方圖均衡化技術來處理影象,能擴充套件影象的動態範圍,擴寬灰度等級範圍,提高對比度。
直方圖均衡化可以調整較暗的圖片,圖片較暗,動態範圍低,直方圖灰度等級偏暗,均衡化後灰度基本平均分佈。。
使用直方圖均衡化,在處理較暗的影象時特別有效,如下測試。
Mat blue, green, red, dst; blue = bgr_planes[0]; green = bgr_planes[1]; red = bgr_planes[2]; equalizeHist(blue, blue); equalizeHist(green, green); equalizeHist(red, red); merge(bgr_planes, 3, dst); imshow("均衡化圖", dst); vector<Mat> bgr_planes2; split(dst, bgr_planes2); calcHist(&bgr_planes2[0], 1, 0, Mat(), b_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes2[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes2[2], 1, 0, Mat(), r_hist, 1, &histsize, &histRanges, true, false); histImg = Mat::zeros(256, 256 * 3, CV_8UC3); for (int h = 0; h < 256; h++) { float binVal_r = r_hist.at<float>(h); float binVal_g = g_hist.at<float>(h); float binVal_b = b_hist.at<float>(h); rectangle(histImg, Point(h, 256 - 1), Point(h + 1, 256 - binVal_r), Scalar(255, 0, 0)); rectangle(histImg, Point(h + 255, 256 - 1), Point(h + 255 + 1, 256 - binVal_g), Scalar(0, 255, 0)); rectangle(histImg, Point(h + 510, 256 - 1), Point(h + 510 + 1, 256 - binVal_b), Scalar(0, 0, 255)); }
輸出影象對比:
處理後的圖片亮度提高,動態範圍擴大,這裡有一個問題,由於是全域性處理,車牌由於反光材料本來就屬於最亮的區域,均衡化後更亮了,導致車牌亮度過曝反而更加難識別了,所以需要特定的直方圖處理。
對比直方圖:
5、參考文獻
1、《OpenCV3 程式設計入門》,電子工業出版社,毛星雨著
2、《學習OpenCV》,清華大學出版社,Gary Bradski, Adrian kaehler著
3、OpenCV影象直方圖
https://blog.csdn.net/leonardohaig/article/details/88240112
4、影象處理基礎(8):影象的灰度直方圖、直方圖均衡化、直方圖規定化(匹配)
https://www.cnblogs.com/wangguchangqing/p/7098213.html
5、OpenCV實現影象的直方圖處理
https://www.cnblogs.com/noticeable/p/10449867.html
6、【OpenCV學習筆記】之直方圖(Histogram)
https://blog.csdn.net/zhu_hongji/article/details/81663161
技術部落格,轉載請註明。
https://www.cnblogs.com/pingwen/p/12380776.html