本文的算法並不是我自己提出的,而是一些論文中提出的,詳見 :
1、基於圖像分析的偏色檢測及顏色校正方法 徐曉昭 , 蔡軼珩 , 劉長江 , 賈克斌 , 沈蘭蓀
為方便大家理解,這里還是從這些論文里摘取些具體的過程予以描述。
RGB顏色空間是最簡單的一種顏色空間,但是RGB顏色空間最大的局限性在於當用歐氏距離來刻畫兩種顏色之間的差異時,所計算出的兩種顏色之間的距無法正確表征人們實際所感知到的這兩種顏色之間的真實差異。采用CIE Lab顏色空間,此空間所計算出來的顏色之間的距離與實際感知上的差別基本一致。其直方圖可以客觀的反映圖像色偏程度,在CIE Lab下進行偏色圖像的自動檢測更為合理。
經過對正常圖像和偏色圖像的分析發現,如果在ab色度坐標平面上的直方圖中,色度分布基本上為單峰值,或者分布較為集中,而色度平均值D又較大時,一般都存在色偏,而且色度平均值越大,色偏越嚴重。然而,如果在ab色度坐標平面上的直方圖中色度分布存在明顯的多峰值,而且較為分散時,圖像色偏程度將大大減輕,甚至沒有色偏。
如上圖所示,第一個美女圖明顯就偏色,其[a,b]直方圖明顯有只有一個波峰,而第二個美女圖則很協調,[a,b]直方圖也分布的很均勻。
因此引入等效圓的概念 ,采用圖像平均色度 D和色度中心距 M的比值 ,即偏色因子 K來衡量圖像的偏色程度。其計算方法如下式
式中 ,M、 N分別為圖像的寬和高,以像素為單位。在 a - b色度平面上,等效圓的中心坐標為 ( da , db ) ,半徑為 M 。等效圓的中心到 a - b色度平面中性軸原點為 ( a = 0, b = 0)的距離 D 。由等效圓在 a - b色度平面上的具體位置,來判斷圖像整體的偏色。da > 0,偏紅,否則偏綠。db > 0,偏黃,否則偏藍。引入偏色因子 K, K值越大 ,偏色越嚴重。
按照上述細路編制的代碼如下:
//***************************************************************************************** //** 開發日期 : 2013-12-20 //** 作 者 : laviewpbt //** 聯系方式: 33184777 //** 修改日期 : 2013-7-15 //** 版 本 : Version 1.0.0 //** 轉載請不要刪除以上信息 //** 皮膚檢測技術的研究及改進 重慶大學碩士論文 魏菁 //***************************************************************************************** public static double GetColorCastFactor(Bitmap Bmp) { if (Bmp.PixelFormat != PixelFormat.Format24bppRgb) throw new ArgumentException("Only Support PixelFormat24RGB format Image."); Bitmap Lab = new Bitmap(Bmp.Width, Bmp.Height, PixelFormat.Format24bppRgb); int X, Y; int Width, Height, Stride; BitmapData BmpData, LabData; byte* Pointer; int SumA = 0, SumB = 0; double MsqA = 0, MsqB = 0, AvgA, AvgB; int A, B; int[] HistA = new int[256]; int[] HistB = new int[256]; BmpData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); LabData = Lab.LockBits(new Rectangle(0, 0, Lab.Width, Lab.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); Width = Bmp.Width; Height = Bmp.Height; Stride = BmpData.Stride; for (Y = 0; Y < Height; Y++) ColorSpace.RGBLAB.ToLAB((byte*)BmpData.Scan0 + Y * Stride, (byte*)LabData.Scan0 + Y * Stride, Bmp.Width); for (Y = 0; Y < Height; Y++) { Pointer = (byte*)LabData.Scan0 + Y * Stride; for (X = 0; X < Width; X++) { A = *(Pointer + 1); B = *(Pointer + 2); SumA += A; SumB += B; HistA[A]++; HistB[B]++; Pointer += 3; } } AvgA = (double)SumA / (Width * Height) - 128; // 必須歸一化到[-128,,127]范圍內 AvgB = (double)SumB / (Width * Height) - 128; for (Y = 0; Y < 256; Y++) { MsqA += (double)(Math.Abs(Y - AvgA - 128) * HistA[Y]) / (Width * Height); // 用方差的方式結果有問題 MsqB += (double)(Math.Abs(Y - AvgB - 128) * HistB[Y]) / (Width * Height); } Bmp.UnlockBits(BmpData); Lab.UnlockBits(LabData); Lab.Dispose(); return Math.Sqrt(AvgA * AvgA + AvgB * AvgB) / Math.Sqrt(MsqA * MsqA + MsqB * MsqB); }
其中的RGB到LAB空間轉換部分代碼及其優化可參考:顏色空間系列2: RGB和CIELAB顏色空間的轉換及優化算法
代碼很簡答吧,朋友們可以先按照公式自己編寫下,然后再和我的最比下。看看那些地方的優化值得學習吧。
按照上述我們做一些測試:
cast = 3.297788 cast=0.37389 cast=0.5028 cast=1.82749 cast=1.699
我們在測試一些明顯偏色的圖像。
cast =3.52449 cast =5.74808 cast=2.50289 cast =4.08616
上述四幅圖的偏色明顯比較驗證,偏色因子的值也較大。
在看看一些比較正常的照片吧.
cast=0.43784 cast =0.90216 cast=0.51927 cast =1.216
綜合來說,cast值不大於1.5我們可以認為其整體圖像偏色的可能性不大,當然這個值取多少可能還是需要和實際情況結合的。
xiaotie在其博客里也曬出了它的一種檢測偏色的結果,我這里的計算復雜度可能沒他哪里的復雜,不過也可以借鑒參考的。
完整的代碼見:http://files.cnblogs.com/Imageshop/ColorCast.rar
博客園的網站分類里居然沒有圖像處理一欄,只有計算機圖形學一項,其實搞這一行的都知道,這兩個是完全不同的行業。希望博客園考慮增加圖像處理一欄。
***************************作者: laviewpbt 時間: 2013.7.15 聯系QQ: 33184777 轉載請保留本行信息*************************