OpenCV3入門(十一)圖像直方圖

一、直方圖的概念

灰度直方圖是灰度級的函數,描述的是圖像中具備該灰度級的像元的個數。肯定圖像像素的灰度值範圍,以適當的灰度間隔爲單位將其劃分爲若干等級,以橫軸表示灰度級,以縱軸表示每一灰度級具備的像素數或該像素佔總像元數的比例值,作出的條形統計圖即爲灰度直方圖。灰度直方圖:橫座標是灰度,縱座標是該灰度在圖像中出現的次數。html

圖像直方圖能夠表示圖像中亮度分佈,能借助直方圖瞭解須要如何調整亮度分佈,直方圖中左側表示黑色、較暗的區域,右側表示白色、較亮的區域。計算機視覺領域常藉助直方圖來實現圖像的二值化。編程

二、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:須要統計直方圖的第幾通道spa

InputArray mask:掩膜,計算掩膜內的直方圖.net

OutputArray hist:輸出的直方圖的數組3d

int dims:直方圖的維度,須要統計直方圖通道的個數code

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);

輸出結果爲:

三、直方圖均衡化

直方圖均衡化即灰度均衡化,經過灰度映射,使輸入圖像的灰度轉換爲在每一級灰度上都有近似相同的點數分佈,這樣輸出的直方圖就是均勻的,圖像得到較高的對比度和較大的動態範圍。直方圖均衡化對圖像進行非線性拉伸,從新分配圖像像素值,使必定灰度範圍內的像素數量大體相同。使用直方圖均衡化技術來處理圖像,能擴展圖像的動態範圍,擴寬灰度等級範圍,提升對比度。

直方圖均衡化能夠調整較暗的圖片,圖片較暗,動態範圍低,直方圖灰度等級偏暗,均衡化後灰度基本平均分佈。。

使用直方圖均衡化,在處理較暗的圖像時特別有效,以下測試。

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));
}

輸出圖像對比:

處理後的圖片亮度提升,動態範圍擴大,這裏有一個問題,因爲是全局處理,車牌因爲反光材料原本就屬於最亮的區域,均衡化後更亮了,致使車牌亮度過曝反而更加難識別了,因此須要特定的直方圖處理。

對比直方圖:

五、參考文獻

一、《OpenCV3 編程入門》,電子工業出版社,毛星雨著

二、《學習OpenCV》,清華大學出版社,Gary Bradski, Adrian kaehler著

三、OpenCV圖像直方圖

https://blog.csdn.net/leonardohaig/article/details/88240112

四、圖像處理基礎(8):圖像的灰度直方圖、直方圖均衡化、直方圖規定化(匹配)

http://www.javashuo.com/article/p-ezvpbdnw-hg.html

五、OpenCV實現圖像的直方圖處理

http://www.javashuo.com/article/p-qozckbwv-gc.html

六、【OpenCV學習筆記】之直方圖(Histogram)

https://blog.csdn.net/zhu_hongji/article/details/81663161

 

技術博客,轉載請註明。

http://www.javashuo.com/article/p-fmiezbjw-hm.html

相關文章
相關標籤/搜索