【圖像處理】-005 直方圖均衡

直方圖均衡

1 原理

  首先定義幾個變量,其實這幾個變量在前面幾篇關於直方圖變換的文章中同樣應該定義。

變量 意義
nkn_k 灰度級爲rkr_k的像素的個數
rkr_k kk級灰度
h(rk)h(r_k) 灰度級爲rkr_k的像素的個數
P(rk)P(r_k) 灰度級爲rkr_k的概率估計值
nn 總像素數

由此可見:
h(rk)=nkh(r_k)=n_k
P(rk)=nknP(r_k)=\frac{n_k}{n}

直方圖均衡化是一種灰度變換,經過該變換之後,圖像的直方圖分佈基本符合均勻分佈。
設變換的輸出爲灰度ss,那麼直方圖均衡的變換可以表達爲:
s=T(rk)s = T(r_k)
每一個灰度級經過函數T(r)T(r)變換之後都對應一個輸出灰度級ss,同時T(r)T(r)滿足兩個條件:

  • T(r)T(r)在區間[0,1][0,1]上是單值且單調遞增函數;
  • 0rL10\leq r \leq L-1時,0T(r)L10 \leq T(r) \leq L-1;

第一條約束要求輸入越高的灰度級,變換之後仍然是越高的灰度級,不會出現亮暗翻轉的情況。第二條約束要求變換之後,灰度級仍然在有效範圍之內。

Pr(r)P_{r}(r)Ps(s)P_{s}(s)表示灰度級爲rrss的概率密度,
s=T(r)=(L1)0rpr(w)dws=T(r)=(L-1)\int_{0}^{r}{p_{r}(w)dw}
其中ww是積分變量。公式右邊是概率密度函數的積分,總爲正,因此滿足條件一,當到達積分上限L1L-1時,函數的值爲1,滿足條件二。
ps(s)=pr(r)drdsp_{s}(s)=p_{r}(r)|\frac{dr}{ds}|
dsdr=dT(r)dr=(L1)ddr[0rpr(w)dw]=(L1)pr(r)\frac{ds}{dr}=\frac{dT(r)}{dr}=(L-1)\frac{d}{dr}[\int_{0}^{r}{p_{r}(w)dw}]=(L-1)p_{r}(r)
ps(s)=pr(r)drds=pr(r)1(L1)pr(r)=1L1,0sL1p_{s}(s)=p_{r}(r)|\frac{dr}{ds}|=p_{r}(r)|\frac{1}{(L-1)p_{r}(r)}|=\frac{1}{L-1},0 \leq s \leq L-1
這就說明了經過變換之後,輸出灰度級ss[0,L1][0,L-1]上服從均勻分佈。

將變換離散化之後,得到離散形式下的變換關係:
sk=T(rk)=(L1)j=0kpr(rj)=L1MNj=0knj,k=0,1,2,,L1s_k=T(r_{k})=(L-1)\sum_{j=0}^{k}p_{r}(r_{j})=\frac{L-1}{MN}\sum_{j=0}^{k}n_{j}, k=0,1,2, \dots ,L-1
其中,M,NM,N爲圖像的寬高,LL爲圖像的總灰度級。

2 Matlab實現

2.1 Matlab已有函數

  Matlab中使用函數histeq進行直方圖均衡化。注意,histeq默認情況下,直方圖均衡時灰度等級會被劃分到64個子級中,這導致直接使用默認參數調用時結果的直方圖與手動計算的結果差異較大。

2.2 手動實現

clc;
clear;
close all;

% 對灰度圖進行灰度線性變換
ori_img = imread('../images/18.jpg');
ori_img1 = rgb2gray(ori_img);
[oriHist,oriX] = imhist(ori_img1);

p = oriHist;
all = sum(oriHist);
for i=1:1:256
    p(i) = sum(oriHist(1:i));
end
% p = 255*p;
% p = uint8(p);

[width,height] = size( ori_img1);
gray1 = ori_img1;
for i=1:1:width
    for j = 1:1:height
        gray1(i,j) = 255*p(gray1(i,j)+1)/all;
    end
end

[g1Hist,g1X] = imhist(gray1);

g2 = histeq(ori_img1,256);
[g2Hist,g2X] = imhist(g2);
figure(1),subplot(1,3,1),imshow(ori_img1),title('原圖');subplot(1,3,2),imshow(gray1),title('手動實現直方圖均衡化');subplot(1,3,3),imshow(g2),title('histeq');
figure(3),subplot(1,3,1),stem(oriX,oriHist),title('原圖直方圖');subplot(1,3,2),stem(g1X,g1Hist),title('手動實現直方圖均衡化');subplot(1,3,3),stem(g2X,g2Hist),title('histeq');

3 OpenCV實現

3.1 OpenCV已有函數

  直方圖均衡化在OpenCV中使用函數equalizeHist函數完成。

/** @brief Equalizes the histogram of a grayscale image.

The function equalizes the histogram of the input image using the following algorithm:

- Calculate the histogram \f$H\f$ for src .
- Normalize the histogram so that the sum of histogram bins is 255.
- Compute the integral of the histogram:
\f[H'_i =  \sum _{0  \le j < i} H(j)\f]
- Transform the image using \f$H'\f$ as a look-up table: \f$\texttt{dst}(x,y) = H'(\texttt{src}(x,y))\f$

The algorithm normalizes the brightness and increases the contrast of the image.

@param src Source 8-bit single channel image.
@param dst Destination image of the same size and type as src .
 */
CV_EXPORTS_W void equalizeHist( InputArray src, OutputArray dst );

3.2 C++ 手動實現

創建灰度映射表,具體變換過程使用opencv的LUT函數執行。

void CreateHELT(cv::Mat& hist, cv::Mat&lut)
{
	cv::Mat data(1,256,CV_32FC1,cv::Scalar(0));
	lut = cv::Mat(1, 256, CV_8UC1);
	for (int i = 0; i < data.cols; i++)
	{
		if (i == 0)
		{
			data.at<float>(i) = hist.at<float>(i);
		}
		else
		{
			data.at<float>(i) = data.at<float>(i-1)+hist.at<float>(i);
		}
		float f = 255 * data.at<float>(i);
		if (f < 0)
			f = 0;
		else if (f > 255)
			f = 255;
		lut.at<uchar>(i) = (uchar)(f);
	}
}

4 效果圖

histeq使用256級灰度時的結果:
在這裏插入圖片描述在這裏插入圖片描述
histeq使用默認參數調用時的計算結果:
在這裏插入圖片描述
在這裏插入圖片描述從結果可以看出,histeq的灰度級明顯少。

5 參考

https://blog.csdn.net/timeless_2014/article/details/80389433
https://www.cnblogs.com/whw19818/p/5790680.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章