項目筆記---圖片處理


 

 

最近由於項目上需要對圖片進行二值化處理,就學習了相關的圖片處理上的知識,從開始的二值化的意義到動態閥值檢測二值化等等,並用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/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM