1. 程式人生 > >【VC影象處理】直方圖均衡化

【VC影象處理】直方圖均衡化

/*img 為輸入原圖
outimg為輸出直方圖
probality為輸出的灰度直方概率,是陣列*/
void Histogram(Mat img,Mat &outImg,float *probality)
{
	outImg.create(500,256,CV_8UC3);
	outImg.setTo(Scalar(0,255,0));//outImg.setTo(Scalar::all(255));
	float tmp[256]={0};
	int gray[256]={0};
	int i,j;
	int Width=img.cols;
	int Height=img.rows;
	for( i=0;i<Height;i++)
	{	for(  j=0;j<Width;j++)
	{
		gray[(int)(img.at<uchar>(i,j))]++;

	}

	}
	for(i=0;i<256;i++)
	{
		probality[i]=(float)(gray[i]*1.0f/(Width*Height*1.0f));
	//	tmp[i]=probality[i];
	}
	int max=0;
	for(i=0;i<256;i++)
		if(gray[i]>max)
			max=gray[i];

	for(i=0;i<256;i++)
	{
		tmp[i]=(float)(gray[i]*1.0f/(float)(max*1.0f));
		tmp[i]*=500;
		//cout<<"tmp"<<i<<"="<<tmp[i]<<endl;
	}
	for(i=0;i<256;i++)
	{

		line(outImg,Point(i,500),Point(i,500-(int)tmp[i]),Scalar(255,0,0));
	}
		
}
	/*img原圖
	outimg為輸出直方均衡化後的圖
	probality為輸入的灰度直方概率,是陣列*/
void Histogram_Equalization(Mat img,Mat &OutImg,float *probality)
{
	int Height=img.rows;
	int Width=img.cols;
	OutImg.create(Height,Width,CV_8UC1);
	float temp[256];
	int tab[256];
	int i,j;
	for(i=0;i<256;i++)
	{
		if(i==0)
		{
			temp[0]=probality[0];
		}
		else
		{
			temp[i]=temp[i-1]+probality[i];
		}
		tab[i]=(int)(255.0f*temp[i]+0.5f);
		//cout<<"tab "<<i<<"="<<tab[i]<<endl;
	}

	for(i=0;i<Height;i++)
		for(j=0;j<Width;j++)
			OutImg.at<uchar>(i,j)=(uchar)(tab[(int)(img.at<uchar>(i,j))]);
}
void main()
{
	Mat SrcImg=imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\1.jpg",0);//01.jpg",0);
	if(!SrcImg.data)
		cout<<"讀取圖片錯誤\n";

	Mat ResultImg1,ResultImg2,ResultImg3;
	float a[256];
	Histogram(SrcImg,ResultImg1,a);
	Histogram_Equalization(SrcImg,ResultImg2,a);
	Histogram(ResultImg2,ResultImg3,a);

	imshow("直方圖",ResultImg1);
	imshow("直方圖均衡化處理圖",ResultImg2);
	imshow("處理後的直方圖",ResultImg3);
	imshow("src",SrcImg);
	waitKey(0);

}

多少天過去了,再重新讀、分析,一開始發現都忘光了,但是看了一會兒就懂了,這就是當初做筆記的好處,要不然又得翻書查資料費好大勁兒才能弄明白,記憶就是不斷重複的過程。現在把直方圖再總結如下:

直方圖均衡化:首先要獲得一張圖片的直方圖資料,一張灰度影象的直方圖灰度值0,1,2,3,4,5,6,...,254,255 需要統計這些灰度值的個數gray[(int)(img.at<uchar>(i,j))]++; 特別需要注意這種陣列格式,下標是灰度值索引值,陣列值是個數。這些其實就是直方圖的資料了,為了在一張圖上顯示直方圖,需要歸一化處理,就是找出個數最大的值作為分母。

但是均衡化的話也需要歸一化,他的歸一化方法是用影象的長和寬乘積做分母(總共有多少資料,所有歸一化資料累加和為1)。均衡化就是用這個歸一化的陣列再計算累積積分,所謂的累積積分就是當前項等於前面所有的和,這是一種概率分佈,在累積積分陣列中當是255時候它的值自然為1,然後255*積分陣列,這是最重要的,這就是接下來的對映表。這個對映陣列其實就是對灰度值的一種重新分佈。上面舉得例子灰度值123很多,佔的比重就很大,在積分圖中縱座標就會很高,再乘以255的話就更突出了,這可能就是直方圖均衡化的真諦了。 就是多的灰度值就讓他和其他一般的灰度值有明顯的差距,所謂的拉伸對比度。分析完畢!