直方圖規定化c++實現

    直方圖均衡化能夠自動的擴展圖像灰度的動態範圍從而提高圖像的對比度增強視覺效果。但是並非所有的圖像都適合直方圖均衡化,例如圖像中大部分灰度值接近0時,由於接近0的像素多權重大,根據均衡原理使用(L-1)*累計概率會造成暗像素的值急劇上升,最終圖像亮度變高出現“沖淡效果”。而直方圖規定化是使圖像具有指定的概率密度分佈,在一些情況下能夠獲得更好的處理效果。

簡單敘述一下具體的步驟:

(1)計算圖像直方圖並進行直方圖均衡化得到變化後的灰度。

(2)利用規定的直方圖進行直方圖均衡化獲得變換函數G的所有值,將G的值存入表中。

(3)對於每個均衡化灰度S,在G值得表中找相應的Z值,使得G的值最接近S值,並存儲S到Z的映射。

(4)建立原始圖想灰度R到Z的映射,最後根據映射關係重建圖像,即可獲得均衡化圖像。

    代碼本來想在網上擼一個,結果感覺都看不懂,還是根據原理自己使用C++寫一個吧,關鍵是使用數據結構Map建立映射表。主要代碼封裝成下面函數HistogramSpecification(Mat &src, Mat &dst, float zhist[])。

/************************************************
@參數:Mat &src  輸入圖像
@參數:Mat &dst  輸出圖像
@參數:float zhist[] 規定化的歸一化直方圖
************************************************/
void HistogramSpecification(Mat &src, Mat &dst, float zhist[])
{
	src.copyTo(dst);     //src拷貝到dst

	int h = src.rows;    //圖像高度
	int w = src.cols;    //圖像寬度

	int hist[256] = {0};  //各級像素數目
	int S[256] = { 0 };
	map<int, int> S2Z;    //S到Z的映射
	map<int, int> r2z;    //r到Z的映射

	//直方圖統計
	for (int i = 0; i < h; i++) {
		uchar* p = src.ptr<uchar>(i);
		for (int j = 0; j < w; j++){
			int vaule = p[j];
			hist[vaule]++;
		}
	}

	//歸一化累加直方圖
	float sumhist[256] = { 0 };
	for (int i = 0; i < 256; i++){
		int sum = 0;
		for (int j = 0; j <= i; j++)
			sum += hist[j];
		sumhist[i] = sum*1.0 / (h*w);
	}

	//根據sumhist建立均衡化後灰度級數組S
	for (int i = 0; i < 256; i++)
		S[i] = 255 * sumhist[i] + 0.5;
	
	//根據zsumhist建立均衡化後灰度級數組G
	int G[256] = { 0 };
	float zsumhist[256] = { 0.0 };

	for (int i = 0; i < 256; i++){
		float sum = 0;
		for (int j = 0; j <= i; j++)
			sum += zhist[j];
		zsumhist[i] = sum;
	}

	for (int i = 0; i < 256; i++)
		G[i] = zsumhist[i] * 255 + 0.5;

	//令G(Z)=S 建立S->Z的映射表
	for (int i = 0; i < 256; i++) {
		for (int j = 1; j < 256; j++){
			if (abs(S[i] - G[j - 1]) < abs(S[i] - G[j]))
			{
				S2Z[S[i]] = j - 1; 
				break;
			}
		}
	}
	S2Z[S[255]] = G[255];

	//建立r->z映射,即爲原像素到規定化像素的映射
	for (int i = 0; i < 256; i++)
		r2z[i] = S2Z[S[i]];

	//重建圖像
	for (int i = 0; i < h; i++) {
		uchar *pdata = dst.ptr<uchar>(i);
		for (int j = 0; j < w; j++){
			*(pdata + j) = r2z[*(pdata + j)];
		}
	}
}

由於規定化的直方圖是根據實際需求而設計的,所以沒有統一標準。在這裏我的直方圖如下:

對比一下均衡化的效果和規定化的效果:


    上圖下對比還是比較明顯的,均衡化的效果真的不好,規定化的效果稍微強一點(主要是我使用的規定化直方圖是瞎整的)。若想要獲得更好的效果可以更具實際情況改變規定化直方圖。

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