天天看點

項目筆記---圖檔處理

最近由于項目上需要對圖檔進行二值化處理,就學習了相關的圖檔處理上的知識,從開始的二值化的意義到動态閥值檢測二值化等等,并用C#得以應用,學到了很多的知識和大家分享下我個人的經驗,希望對大家有幫助。

二值化

二值化簡而言之是對一副彩色圖檔進行0/1運算,最終顯示一副黑白相間的圖檔,其意義多數在于對二值化處理後的圖檔進行分割識别,一些自動識别的驗證碼工具大多是先進行二值化,然後在模式識别,最終推斷出驗證碼;我的項目中是由于硬體隻支援黑色和白色,是以要對使用者的圖檔進行處理,然後顯示在硬體上。

在深入了解二值化的過程中就發現了很多有意思,或者說十分令我感興趣的東西,就是各種圖檔處理算法。

因為一個普通,色彩少,圖像相對簡單的圖檔經二值化處理後還算能勉強接受。但是一副精美的圖檔在經過二值化處理後顯得十分難看,或根本看不出圖檔有任何意義。這其中大家就開始研究思考。

先補充下知識,因為我覺得如果不把基本原理講清楚的話,可能大家不會發現這些算法是多麼的有意思(當然,也可能是我太喜歡這些東西而已)。過程是這樣的,一副彩色的圖檔要先進行灰階化(有的是 将R+G+B加起來除以3取平均值再付給R=G=B,也可以依據權值進行灰階劃分,如(0.299 * r + 0.587 * g + 0.114 * b) 這是一個依據人眼對不同RGB顔色的區分度進行優化的灰階算法,很有意思,想不到人類對不同顔色識别輕重還不一樣)。在經過灰階化之後,實際每個顔色的色值是 R=G=B=(0-255之間)的數值,這樣我們當然可以依據127劃分,如果小于127則認為接近黑色0,反之則認為接近白色255,将所有色值依據127劃分後圖像就成為黑白的二值化圖檔。

回過頭來,我們來看看,這樣經過二值化處理的圖檔“失真”還是很嚴重,有沒有什麼辦法能優化呢,當然這難不倒這些研究算法的專家們。

Ordered dithering有序抖動就是一個化腐朽為神奇的算法,具體算法細節不去深究,大概就是依據一個算法矩陣,然後對圖像點進行處理。下面是圖檔對比。

項目筆記---圖檔處理

這幅圖檔是原圖

項目筆記---圖檔處理

這幅圖是已128為全局閥值的二值化圖檔

項目筆記---圖檔處理

這幅圖是有序抖動處理後的二值化圖檔,黑白的二值化圖檔(并非灰階),所有的點非黑即白,視覺上會産生灰階圖檔的視覺誤差,這就是神奇之處。(注:原圖如果是大圖的話,效果更明顯。)

此外,還有很多優秀的算法對圖檔進行處理,大都是圍繞如何處理判斷“閥值”而産生的。

AForge.Net.Image

在查找C#開源類庫的時候,發現了強大的AForge.Net,您可以先參考其官方網站了解更多詳情。這個開源類庫實在是太強大了,不僅包含圖檔處理的各種算法方式,視訊處理方式,還包含人工智能方面的各種實踐,都是基于C#寫的,代碼整潔程度也是值得學習的,是以,今後如果有時間應該仔細研究研究。而且官方文檔及Sample都十分完善,十分強大。

N多種圖檔處理方式,參照Demo,你會發現使用起來極其簡單~~

代碼樣例

啰嗦了那麼多,下面就示範下代碼如何實作的:

這裡代碼可能不全,請參照官方AForge.NET Framework-2.2.5\Samples\Imaging\FiltersDemo這個Demo

Bitmap temp = AForge.Imaging.Image.Clone(new Bitmap(SrcPic), PixelFormat.Format24bppRgb); // 加載圖檔,并強制轉換成Format24bppRgb這種格式

 
temp = Grayscale.CommonAlgorithms.RMY.Apply(temp); // 将圖檔依照RY算法進行灰階化,很多算法都是先灰階然後再處理的。


pictureBox.Image =(new OrderedDithering()).Apply(sourceImage); // 應用Filter,這裡選取OrderedDithering類型的Filter      

這是應用AForge.Net實作的多種處理圖檔的代碼,很簡單并且擴充性很強,值得學習。

更多代碼請參考官方Sample,有任何問題,請回複我。

後記

雖然有了十分強大的AForge.Net,但是針對一些特定圖檔處理需求還是要自己寫代碼的,當然也可以用AForge實作,這裡我隻是強調一下如果自己手動寫代碼的話是如何處理的并且有哪些需要注意的地方。

首先從彩色圖檔灰階化說起:所謂灰階化就是按照一定的算法将R,G,B的值轉換成同一個值,這其中比較普遍的做法一個是(R+G+B)/3取平均值,另一個是權重算法依據人眼對不同顔色的識别而權值化的算法 (0.299 * r + 0.587 * g + 0.114 * b) = R=G=B。

/// <summary>
        /// 灰階化實作
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="foo"></param>
        /// <returns></returns>
        private static Bitmap WeightGrayScaleImple(Bitmap bmp, Func<double, double, double, byte> foo)
        {
            Bitmap thisMap = bmp;
            Rectangle rect = new Rectangle(0, 0, thisMap.Width, thisMap.Height);
            BitmapData bmpData = thisMap.LockBits(rect, ImageLockMode.ReadWrite, thisMap.PixelFormat);
            unsafe
            {
                byte* ptr = (byte*)(bmpData.Scan0);
                for (int i = 0; i < bmpData.Height; i++)
                {
                    for (int j = 0; j < bmpData.Width; j++)
                    {
                        ptr[0] = ptr[1] = ptr[2] = foo(ptr[2], ptr[1], ptr[0]);
                        ptr += 4;
                    }
                    ptr += bmpData.Stride - bmpData.Width * 4;
                }
            }
            thisMap.UnlockBits(bmpData);
            return thisMap;
        }      
     // Foo 實作
     private static byte WeightGrayBinaraztion(double r, double g, double b)
        {
            return (byte)(0.299 * r + 0.587 * g + 0.114 * b);// Feature Weight 
        }      

注:在C#下對圖檔值這種指針類型的處理時,必須啟用unsafe,否則效率極其低。(項目中打開unsafe開關:項目屬性--->生成--->允許不安全代碼)

基本上以上内容就是項目中所用到的處理圖檔的所有内容,希望通過以上内容的介紹對大家有幫助。 有問題,歡迎回複,謝謝。

Reference

http://en.wikipedia.org/wiki/Ordered_dithering

http://www.aforgenet.com/aforge/framework/

作者:Stephen Cui

出處:http://www.cnblogs.com/cuiyansong

版權聲明:文章屬于本人及部落格園共有,凡是沒有标注[轉載]的,請在文章末尾加入我的部落格位址。

如果您覺得文章寫的還不錯,請點選“推薦一下”,謝謝。