標籤:style blog http color 使用 os io strong
本文主要對彩色圖片灰階化的方法及其實現過程進行總結,最終給出Emgu CV實現的代碼。
一、灰階化原理及數學實現(轉載自——《映像灰階化方法總結及其VC實現》 該篇文章使用opencv實現,後面附有代碼,可以好好學習一下,比我寫的好\(^o^)/~)
影像處理時,通常第一個步驟就是對採集到的彩色映像進行灰階化,這是因為黑白照片資料量小,相比彩照更易實現即時演算法,另一方面黑白照片是由未處理的光線所形成的照片,因此從影像處理學角度來看,這種未經特殊濾光處理的圖片所涵蓋的資訊更有價值。
目前,在影像處理過程中,最常用的彩色圖片格式有RGB,HSV、YUV以及HLS三種。
1、RGB空間映像
定義於RGB空間的彩色圖,其每個像素點的色彩由R、G、B三個分量共同決定。每個分量在記憶體所佔的位元共同決定了映像深度,即每個像素點所佔的位元組數。以常見的24深度彩色RGB圖來說,其三個分量各佔1個位元組,這樣每個分量可以取值為0~255,這樣一個像素點可以有1600多萬(255*255*255)的顏色的變化範圍。對這樣一幅彩色圖來說,其對應的灰階圖則是只有8位的映像深度(可認為它是RGB三個分量相等),這也說明了灰階圖影像處理所需的計算量確實要少。不過需要注意的是,雖然丟失了一些顏色等級,但是從整幅映像的整體和局部的色彩以及亮度等級分布特徵來看,灰階圖描述與彩色圖的描述是一致的。
對於RGB映像進行灰階化,通俗點說就是對映像的RGB三個分量進行加權平均得到最終的灰階值。最常見的加權方法如下:
1)Gray=B;Gray=G;Gray=R
2)Gray=max(B+G+R)
3)Gray=(B+G+R)/3
4)Gray= 0.072169B+ 0.715160G+ 0.212671R
5)Gray= 0.11B+ 0.59G+ 0.3R
這三種方法中,第一種為分量法,即用RGB三個分量的某一個分量作為該點的灰階值;第二種方法為最大值法,將彩色映像中的三分量亮度的最大值作為灰階圖的灰階值。第三種方法將彩色映像中的三分量亮度求平均得到一個灰階圖;後兩種都是屬於加權平均法,其中第四種是OpenCV開放庫所採用的灰階權值,第五種為從人體生理學角度所提出的一種權值(人眼對綠色的敏感最高,對藍色敏感最低)。
2、其他色彩空間的灰階化
關於HSV以及HLS色彩空間的彩色圖灰階化,可以參考網頁《HSL和HSV色彩空間》,該網頁中所述方法可將幾種不同顏色表達方式進行轉換,將其轉換到RGB空間,然後再採用上述公式進行灰階化。
關於YUV空間的彩色映像,其Y的分量的物理意義本身就是像素點的亮度,由該值反映亮度等級,因此可根據RGB和YUV色彩空間的變化關係建立亮度Y與R、G、B三個顏色分量的對應:Y=0.3R+0.59G+0.11B,以這個亮度值表達映像的灰階值。
3、編程小貼士(可以先不看,看完文章再回來看,本篇文章的程式用不到,留著以後用)
代碼實現中,以最後一種方法為例,用到了如下代碼:
Gray= (0.11* Blue + 0.59* Green + 0.30* Red);
實際電腦處理時,這種方法已經很快了,但實際上還存在可以最佳化的餘地。以上代碼所採用的是浮點運算。而在影像處理中,速度就是生命,即時性往往是很重要的指標,這就要求我們在實現演算法時必須考慮到代碼的效率問題。所以有一個原則:在影像處理中,能不用浮點運算,就最好不要用!
因此,上述代碼可以等效的最佳化為:
Gray = (30 * Red + 59 *Green + 11 * Blue) / 100;
這樣一改,可以有效避免浮點運算,因此可以提高代碼的效率
對這行代碼還可以繼續改進為如下:
Gray= HiByte(77 * Red + 151 * Green + 28 * Blue);
其中77,151,28分別除以256,即為上文的三個係數。
同樣的,還可以實現為:
Gray= (77 * Red + 151 * Green + 28 * Blue) shr 8;
這種方法實現了移位元運算,避免了除法,效率上又有所提高。
關於具體的代碼效率問題,可以參考博文《由映像的灰階化看基本影像處理》。
二、Emgu CV實現(轉載)
重點參看以下兩篇文章
EmguCV圖片灰階化
C# OpenCV學習筆記四之映像二值化
步驟:
1、 建立一個Windows表單應用程式,將Form1的Text屬性改為“灰階映像ToGrayImage”,Name屬性改為“ToGrayImage”
2、 給表單添加一個按鈕,Name屬性改為“sltImageBtn”,Text屬性改為“選擇圖片...”
3、 給表單添加一個OpenFileDialog,用來選擇圖片檔案,將Filter屬性設定為“Image File|*.jpg;*.png;*.bmp;*.gif;”
4、 給表單添加二個PictureBox,並將SizeModel設定為Zoom
5、 布局顯示效果如下:
6、 雙擊按鈕,系統會自動產生click空事件
7、 添加EmguCV的引用,這裡添加最常用的3個【Emgu.CV.dll、Emgu.CV.UI.dll、Emgu.Util.dll】
8、 添加命名空間
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System.Runtime.InteropServices;
9、 編寫代碼
/// <summary> ///選擇圖片事件,將彩色圖片轉換為灰階映像 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void sltImageBtn_Click(object sender, EventArgs e) { if (openFileDialog1.ShowDialog() == DialogResult.OK) { //原圖顯示 IntPtr srcimg = CvInvoke.cvLoadImage(openFileDialog1.FileName, Emgu.CV.CvEnum.LOAD_IMAGE_TYPE.CV_LOAD_IMAGE_ANYCOLOR); if (srcimg == null) { MessageBox.Show("no pic!"); return; } /* IplImage* 轉換為Bitmap */ MIplImage srcmi = (MIplImage)Marshal.PtrToStructure(srcimg, typeof(MIplImage)); Image<Bgr, Byte> srcimage = new Image<Bgr, Byte>(srcmi.width, srcmi.height, srcmi.widthStep, srcmi.imageData); pictureBox1.Image = srcimage.ToBitmap(); //灰階圖顯示 IntPtr grayimg = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(srcimg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1); CvInvoke.cvCvtColor(srcimg, grayimg, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_RGB2GRAY); MIplImage graymi = (MIplImage)Marshal.PtrToStructure(grayimg, typeof(MIplImage)); //和彩色映像顯示採用函數不一致,如果繼續使用上面函數,會報記憶體錯誤 Image<Gray, Byte> grayimage = new Image<Gray, Byte>(graymi.width, graymi.height, graymi.widthStep, graymi.imageData); pictureBox2.Image = grayimage.ToBitmap(); CvInvoke.cvWaitKey(0); CvInvoke.cvReleaseImage(ref srcimg); CvInvoke.cvReleaseImage(ref grayimg); } }
由於時間倉促,《映像灰階化方法總結及其VC實現》中灰階的其他演算法還不懂得如何在emgucv中實現,還需要研究一下。