當影像的色階集中於集中於某些極端的位置時,會導致影像顏色非常相近,因此人眼難以辨別其細節。
此時可以採用"Histogram equalization",將其資訊等比例放大後影像則可更清晰可視。
直方圖等化使用機率分佈, 將原先的亮度分佈重新均勻的等化到新的亮度值.。
其數學式如下所示 :
較為常見之效果如下圖所示,
原本R,G,B之顏色較為集中於某個區間,經過"Histogram equalization"後,其資訊被平均分配使得該影像經由"Histogram equalization"後影像更為清晰。
C#
private static Bitmap histogramEqualization(Bitmap bitmap)
{
//統計
int[,] statistics = new int[3,COLOR_SIZE_RANGE];
int w = bitmap.Width;
int h = bitmap.Height;
int total = w * h;
HistogramEqualizationStatistics(bitmap, ref statistics); //統計
//運算
Console.WriteLine(statistics[0, 72]);
for (int i = 0; i < COLOR_SIZE_RANGE; i++)
{
int rCount = 0, gCount = 0, bCount = 0;
rCount = (int)(statistics[ImageExtract.COLOR_R, i] + ((i == 0) ? 0 : statistics[ImageExtract.COLOR_R, i - 1]));
gCount = (int)(statistics[ImageExtract.COLOR_G, i] + ((i == 0) ? 0 : statistics[ImageExtract.COLOR_G, i - 1]));
bCount = (int)(statistics[ImageExtract.COLOR_B, i] + ((i == 0) ? 0 : statistics[ImageExtract.COLOR_B, i - 1]));
statistics[ImageExtract.COLOR_R, i] = rCount;
statistics[ImageExtract.COLOR_G, i] = gCount;
statistics[ImageExtract.COLOR_B, i] = bCount;
}
//填數
Bitmap resBitmap = HistogramEqualizationFillIn(bitmap, total, statistics);
return resBitmap;
}
HistogramEqualizationFillIn 負責將影像進行直方圖等化之運算。
private static Bitmap HistogramEqualizationFillIn(Bitmap bitmap, int total, int[,] statistics)
{
int width = bitmap.Width;
int height = bitmap.Height;
int R = 0, G = 1, B = 2;
System.IntPtr srcScan, dstScan;
BitmapData srcBmData, dstBmData;
Bitmap dstBitmap = ImageExtract.InitPonitMethod(bitmap, width, height, out srcScan, out dstScan, out srcBmData, out dstBmData);
unsafe //啟動不安全代碼
{
byte* srcP = (byte*)srcScan;
byte* dstP = (byte*)dstScan;
int srcOffset = srcBmData.Stride - width * 3;
int dstOffset = dstBmData.Stride - width * 3;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++, srcP += 3, dstP += 3)
{
dstP[2] = (byte)(((double)statistics[R, srcP[2]] / total) * (COLOR_SIZE_RANGE - 1));
dstP[1] = (byte)(((double)statistics[G, srcP[1]] / total) * (COLOR_SIZE_RANGE - 1));
dstP[0] = (byte)(((double)statistics[B, srcP[0]] / total) * (COLOR_SIZE_RANGE - 1));
}
srcP += srcOffset;
dstP += dstOffset;
}
}
bitmap.UnlockBits(srcBmData);
dstBitmap.UnlockBits(dstBmData);
return dstBitmap;
}
完整程式碼(連結)
文章標籤
全站熱搜
留言列表