直方圖均衡化又稱直方圖修平,是一種很重要的非線性點運算。使用該方法可以加強圖像的局部對比度,尤其是當圖像的有用數據的對比度相當接近的時候。通過這種方法,亮度可以更好的在直方圖上分布。
直方圖均衡化的基本思想是把原始圖像的直方圖變換為均勻分布的形式。這樣增加了灰度值的動態范圍,從而達到增強圖像整體對比度的效果。
算法步驟:
1)計算圖像f(x,y)的各灰度級中像素出現的概率p(i)。
2) 計算p的累計概率函數c(i),c即為圖像的累計歸一化直方圖
3)將c(i)縮放至0~255范圍內
/// <summary> /// 直方圖均衡化 直方圖均衡化就是對圖像進行非線性拉伸,重新分配圖像像素值,使一定灰度范圍內的像素數量大致相同 /// 增大對比度,從而達到圖像增強的目的。是圖像處理領域中利用圖像直方圖對對比度進行調整的方法 /// </summary> /// <param name="srcBmp">原始圖像</param> /// <param name="dstBmp">處理后圖像</param> /// <returns>處理成功 true 失敗 false</returns> public static bool Balance(Bitmap srcBmp, out Bitmap dstBmp) { if (srcBmp == null) { dstBmp = null; return false; } int[] histogramArrayR = new int[256];//各個灰度級的像素數R int[] histogramArrayG = new int[256];//各個灰度級的像素數G int[] histogramArrayB = new int[256];//各個灰度級的像素數B int[] tempArrayR = new int[256]; int[] tempArrayG = new int[256]; int[] tempArrayB = new int[256]; byte[] pixelMapR = new byte[256]; byte[] pixelMapG = new byte[256]; byte[] pixelMapB = new byte[256]; dstBmp = new Bitmap(srcBmp); Rectangle rt = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height); BitmapData bmpData = dstBmp.LockBits(rt, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); unsafe { //統計各個灰度級的像素個數 for (int i = 0; i < bmpData.Height; i++) { byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride; for (int j = 0; j < bmpData.Width; j++) { histogramArrayB[*(ptr + j * 3)]++; histogramArrayG[*(ptr + j * 3 + 1)]++; histogramArrayR[*(ptr + j * 3 + 2)]++; } } //計算各個灰度級的累計分布函數 for (int i = 0; i < 256; i++) { if (i != 0) { tempArrayB[i] = tempArrayB[i - 1] + histogramArrayB[i]; tempArrayG[i] = tempArrayG[i - 1] + histogramArrayG[i]; tempArrayR[i] = tempArrayR[i - 1] + histogramArrayR[i]; } else { tempArrayB[0] = histogramArrayB[0]; tempArrayG[0] = histogramArrayG[0]; tempArrayR[0] = histogramArrayR[0]; } //計算累計概率函數,並將值放縮至0~255范圍內 pixelMapB[i] = (byte)(255.0 * tempArrayB[i] / (bmpData.Width * bmpData.Height) + 0.5);//加0.5為了四舍五入取整 pixelMapG[i] = (byte)(255.0 * tempArrayG[i] / (bmpData.Width * bmpData.Height) + 0.5); pixelMapR[i] = (byte)(255.0 * tempArrayR[i] / (bmpData.Width * bmpData.Height) + 0.5); } //映射轉換 for (int i = 0; i < bmpData.Height; i++) { byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride; for (int j = 0; j < bmpData.Width; j++) { *(ptr + j * 3) = pixelMapB[*(ptr + j * 3)]; *(ptr + j * 3 + 1) = pixelMapG[*(ptr + j * 3 + 1)]; *(ptr + j * 3 + 2) = pixelMapR[*(ptr + j * 3 + 2)]; } } } dstBmp.UnlockBits(bmpData); return true; }