初學圖像處理,在常用算法方面,二白實在是有些頭疼。就在昨天,親愛的小白師兄,對迷茫的二白伸出了援手,為二白送來了一大份干貨——圖像處理常用算法總結。二白仔細閱讀了這些干貨,并將其中的代碼跑了幾遍,覺得受益匪淺。在這里,二白將干貨分享給大家。
1.二值化:
圖1 二值化(閾值:140)處理效果
所謂二值化簡單一點講,就是將圖像劃分成黑和白,通過設定一個標準如果大于這個標準就設為白,如果小于這個標準,就設為黑,而這個標準,就叫做閾值。
具體定義如下所示:
下面給出實現的代碼:
//二值化 //函數的參數iTR為閾值 voidCBMPSampleDlg::ThresholdProcess(intiTR) { //讀取BMP文件 m_Dib.AttachMapFile("1.bmp", TRUE); m_Dib.CopyToMapFile("二值化.bmp"); //將像素指針定位到圖像數據的開始 RGBTRIPLE *rgbtri = (RGBTRIPLE *)m_Dib.m_lpImage; //獲得圖像的大小 intiSize = m_Dib.GetSizeImage(); //BMP文件頭指針 BITMAPINFOHEADER * pBmiHeader = (BITMAPINFOHEADER *)m_Dib.m_lpBMIH; //遍歷每一個像素,并判斷每一個像素的分量(RGB),將其與閾值比較,然后進行賦值 for(inti =0; i < iSize/( pBmiHeader->biBitCount /8); i++) { if( (rgbtri[i].rgbtRed < iTR )| (rgbtri[i].rgbtGreen < iTR) | (rgbtri[i].rgbtBlue < iTR) ) ?????????????????? { ??????????????????????????? rgbtri[i].rgbtRed?? = (BYTE)?0; ??????????????????????????? rgbtri[i].rgbtGreen = (BYTE)?0; ??????????????????????????? rgbtri[i].rgbtBlue? = (BYTE)?0; ?????????????????? } ???????????????????else ?????????????????? { ??????????????????????????? rgbtri[i].rgbtRed?? = (BYTE)?255; ??????????????????????????? rgbtri[i].rgbtGreen = (BYTE)?255; ??????????????????????????? rgbtri[i].rgbtBlue? = (BYTE)?255; ?????????????????? } ??????? } ?????????//顯示圖像 ???????? DrawPic(); }
在讀取圖像之后,會將指針定位到圖像像素數據的開始位置,然后獲得圖像的大小,然后通過BMP文件頭獲得圖像的一個像素所占據的二進制的位數,這樣就知道一個像素由幾個字節組成的了,需要注意的是,一個像素不一定是由三個字節組成的,比如是灰度圖像其只需要一個字節來存儲一個像素究竟是灰到什么程度其范圍在0-255 之間,而彩色圖像卻是由三種顏色組成的也就是所說的三原色RGB分別為Red、Green、Blue三種顏色組成,這三種顏色每個分量各占一個字節,所以這里需要三個字節,另外在BMP圖像中還一個結構為RGBQUAD的結構體,這里一個像素占據的是4個字節,其實,這里就涉及到了8位圖像24位圖像以及32位圖像的問題了,所謂的8位圖像其實,每一個像素占一個字節,24位圖像,每一個像素占據3個字節、而32位圖像每一個像素占據4個字節就是這么來的。代碼中,首先會讀取原始圖像文件,文件的格式為BMP的,關于BMP圖像的存儲結構,在接下來的文章中會講到。
2.海報化
圖2 海報化處理效果
所謂的海報化其實就是將每一個像素的分量與224進行與運算,而244的16進制表示可以表示成0xe0,前面介紹了一個像素的分量的范圍在0-255范圍內,所以只需要將這兩個數值的二進制位相與即可完成海報化的處理效果。
下面為實現的具體代碼:
//海報化 voidCBMPSampleDlg::Posterize() { m_Dib.AttachMapFile("1.bmp", TRUE); m_Dib.CopyToMapFile("海報化.bmp"); RGBTRIPLE *rgbtri = (RGBTRIPLE *)m_Dib.m_lpImage; intiSize = m_Dib.GetSizeImage(); BITMAPINFOHEADER * pBmiHeader = (BITMAPINFOHEADER *)m_Dib.m_lpBMIH; for(inti =0; i < iSize/( pBmiHeader->biBitCount /8); i++) { rgbtri[i].rgbtRed = (BYTE) (rgbtri[i].rgbtRed &0xe0); rgbtri[i].rgbtGreen = (BYTE) (rgbtri[i].rgbtGreen &0xe0); rgbtri[i].rgbtBlue = (BYTE) (rgbtri[i].rgbtBlue &0xe0); } DrawPic(); }
上面的這段代碼是參考DirectShow里面的ezrgb24濾鏡這個例子改寫的,另外下面的灰度化也是采用里面的改寫的。
3.灰度化
圖3 灰度化處理效果
灰度化有很多種處理方法,有分量法、最大值法、平均值法以及加權平均值法。
1)分量法
將彩色圖像中的三分量的亮度作為三個灰度圖像的灰度值,可根據應用需要選取一種灰度圖像。
f1(i,j)=R(i,j) f2(i,j)=G(i,j)f3(i,j)=B(i,j)
其中fk(i,j)(k=1,2,3)為轉換后的灰度圖像在(i,j)處的灰度值。
2)最大值法
將彩色圖像中的三分量亮度的最大值作為灰度圖的灰度值。
f(i,j)=max(R(i,j),G(i,j),B(i,j))
3) 平均值法
將彩色圖像中的三分量亮度求平均得到一個灰度圖。
f(i,j)=(R(i,j)+G(i,j)+B(i,j)) /3
4) 加權平均法
根據重要性及其它指標,將三個分量以不同的權值進行加權平均。由于人眼對綠色的敏感最高,對藍色敏感最低,因此,按下式對RGB三分量進行加權平均能得到較合理的灰度圖像。
f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j))
在我們的程序中,我們采用的是加權平均法進行灰度化。
下面為實現的代碼:
//灰度化 voidCBMPSampleDlg::ConvertToGray() { m_Dib.AttachMapFile("1.bmp", TRUE); m_Dib.CopyToMapFile("灰度化.bmp"); RGBTRIPLE *rgbtri = (RGBTRIPLE *)m_Dib.m_lpImage; intiSize = m_Dib.GetSizeImage(); BITMAPINFOHEADER * pBmiHeader = (BITMAPINFOHEADER *)m_Dib.m_lpBMIH; intiGrayvalue =0; //遍歷每一個像素 for(inti =0; i < iSize/( pBmiHeader->biBitCount /8); i++) { iGrayvalue =int( rgbtri[i].rgbtBlue *0.11+ rgbtri[i].rgbtGreen *0.59+ rgbtri[i].rgbtRed *0.3); rgbtri[i].rgbtRed = (BYTE) iGrayvalue; rgbtri[i].rgbtGreen = (BYTE) iGrayvalue; rgbtri[i].rgbtBlue = (BYTE) iGrayvalue; } DrawPic(); }
在上述代碼中,通過遍歷每一個像素,然后計算該像素的三個分量的加權平均值,將三個分量設置成同一個值,這樣就實現了對圖像的灰度化處理。
4.模糊化
圖4 模糊化處理效果
其實所謂的模糊化,就是將各個像素的相鄰的像素的各個分量的值相加,然后除以2就可以實現對圖像的模糊處理。
下面給出代碼:
//模糊化 void CBMPSampleDlg::Blur() { m_Dib.AttachMapFile("1.bmp",TRUE); m_Dib.CopyToMapFile("模糊化.bmp"); RGBTRIPLE *rgbtri = (RGBTRIPLE *)m_Dib.m_lpImage; int iSize = m_Dib.GetSizeImage(); BITMAPINFOHEADER * pBmiHeader = (BITMAPINFOHEADER *)m_Dib.m_lpBMIH; LONG lHeight = pBmiHeader->biHeight; LONG lWidth = pBmiHeader->biWidth; for(int y =0; y < lHeight; y++) { ???????????????????for?(int x =?2?; x < lWidth; x++, rgbtri ++) { ??????????????????????????? rgbtri->rgbtRed = (BYTE) ((rgbtri->rgbtRed + rgbtri[2].rgbtRed) >>1); rgbtri->rgbtGreen = (BYTE) ((rgbtri->rgbtGreen + rgbtri[2].rgbtGreen) >>1); rgbtri->rgbtBlue = (BYTE) ((rgbtri->rgbtBlue + rgbtri[2].rgbtBlue) >>1); } rgbtri +=2; } DrawPic(); }
上面的代碼同樣是遍歷每一個像素將前一個像素和后一個像素相加,然后將獲得的值右移一位,這樣就能實現除以2的效果,之所以做位運算,是因為位運算的速度比除法運算要快很多。
-
圖像處理
+關注
關注
27文章
1292瀏覽量
56747 -
算法
+關注
關注
23文章
4612瀏覽量
92901 -
代碼
+關注
關注
30文章
4788瀏覽量
68616
原文標題:數字圖像基本處理算法小結
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論