二值圖像是一種簡(jiǎn)單的圖像格式,,它只有兩個(gè)灰度級(jí),即"0"表示黑色的像素點(diǎn),,"255"表示白色的像素點(diǎn),,至于如何從一幅普通的圖像獲得二值圖像,請(qǐng)參考我近期在天極網(wǎng)上發(fā)表的《Visual C++編程實(shí)現(xiàn)圖像的分割》一文,。二值圖像處理在圖像處理領(lǐng)域占據(jù)很重要的位置,,在具體的圖像處理應(yīng)用系統(tǒng)中,往往需要對(duì)于獲得的二值圖像再進(jìn)一步進(jìn)行處理,,以有利于后期的識(shí)別工作,。二值圖像處理運(yùn)算是從數(shù)學(xué)形態(tài)學(xué)下的集合論方法發(fā)展起來的,盡管它的基本運(yùn)算很簡(jiǎn)單,但是卻可以產(chǎn)生復(fù)雜的效果,。常用的二值圖像處理操作有許多方法,,如腐蝕,、膨脹、細(xì)化,、開運(yùn)算和閉運(yùn)算等等,。本文對(duì)這些內(nèi)容作些研究探討,
希望對(duì)愛好圖像處理的朋友有所幫助,。
一,、腐蝕和膨脹
形態(tài)學(xué)是一門新興科學(xué),它的用途主要是獲取物體拓?fù)浜徒Y(jié)果信息,,它通過物體和結(jié)構(gòu)元素相互作用的某些運(yùn)算,得到物體更本質(zhì)的形態(tài),。它在圖像處理中的應(yīng)用主要是:
1.利用形態(tài)學(xué)的基本運(yùn)算,,對(duì)圖像進(jìn)行觀察和處理,從而達(dá)到改善圖像質(zhì)量的目的,;
2.描述和定義圖像的各種幾何參數(shù)和特征,,如面積,周長(zhǎng),,連通度,,顆粒度,骨架和方向性,。
限于篇幅,,我們只介紹簡(jiǎn)單二值圖像的形態(tài)學(xué)運(yùn)算,對(duì)于灰度圖像的形態(tài)學(xué)運(yùn)算,,有興趣的讀者可以看有關(guān)的參考書,。二值圖像基本的形態(tài)學(xué)運(yùn)算是腐蝕和膨脹,簡(jiǎn)單的腐蝕是消除物體的所有邊界點(diǎn)的一種過程,,其結(jié)果是使剩下的物體沿其周邊比原物體小一個(gè)像素的面積,。如果物體是圓的,它的直徑在每次腐蝕后將減少兩個(gè)像素,,如果物體在某一點(diǎn)處任意方向上連通的像素小于三個(gè),,那么該物體經(jīng)過一次腐蝕后將在該點(diǎn)處分裂為二個(gè)物體。簡(jiǎn)單的膨脹運(yùn)算是將與某物體接觸的所有背景點(diǎn)合并到該物體中的過程,。過程的結(jié)果是使物體的面積增大了相應(yīng)數(shù)量的點(diǎn),,如果物體是圓的,它的直徑在每次膨脹后將增大兩個(gè)像素,。如果兩個(gè)物體在某一點(diǎn)的任意方向相隔少于三個(gè)像素,,它們將在該點(diǎn)連通起來。
下面給出具體的實(shí)現(xiàn)腐蝕和膨脹的函數(shù)代碼:
////////////////////////////////二值圖像腐蝕操作函數(shù)
BOOL ImageErosion(BYTE *pData,int Width,int Height)
{//pData為圖像數(shù)據(jù)的指針,,Width和Height為圖像的寬和高,;
BYTE* pData1;
int m,n,i,j,sum,k,sum1;
BOOL bErosion;
if(pData==NULL)
{
AfxMessageBox("圖像數(shù)據(jù)為空,,請(qǐng)讀取圖像數(shù)據(jù)");
return FALSE;
}
//申請(qǐng)空間,pData1存放處理后的數(shù)據(jù),;
pData1=(BYTE*)new char[WIDTHBYTES(Width*8)*Height];
if(pData1==NULL)
{
AfxMessageBox("圖像緩沖數(shù)據(jù)區(qū)申請(qǐng)失敗,,請(qǐng)重新申請(qǐng)圖像數(shù)據(jù)緩沖區(qū)");
return FALSE ;
}
memcpy(pData1,pData,WIDTHBYTES(Width*8)*Height);
for(i=10;i<Height-10;i++)
for(j=32;j<Width-32;j++)
{
bErosion=FALSE;
sum=*(pData+WIDTHBYTES(Width*8)*i+j);
if(sum==255)
{
//求像素點(diǎn)八鄰域的灰度均值;
for(m=-1;m<2;m++)
{
for(n=-1;n<2;n++)
{
sum1=*(pData+WIDTHBYTES(Width*8)*(i+m)+j+n);
if(sum1==0)
{
*(pData1+WIDTHBYTES(Width*8)*i+j)=0;
bErosion=TRUE;
break;
}
}
if(bErosion)
{
bErosion=FALSE;
break;
}
}
}
}
memcpy(pData,pData1,WIDTHBYTES(Width*8)*Height);
return TRUE;
}
////////////////////////////////////二值圖像的膨脹操作
BOOL ImageDilation(BYTE *pData,int Width,int Height)
{
BYTE* pData1;
int m,n,i,j,sum,k,sum1;
BOOL bDilation;
if(pData==NULL)
{
AfxMessageBox("圖像數(shù)據(jù)為空,,請(qǐng)讀取圖像數(shù)據(jù)");
return FALSE;
}
//申請(qǐng)空間,,pData1存放處理后的數(shù)據(jù);
pData1=(BYTE*)new char[WIDTHBYTES(Width*8)*Height];
if(pData1==NULL)
{
AfxMessageBox("圖像緩沖數(shù)據(jù)區(qū)申請(qǐng)失敗,,請(qǐng)重新申請(qǐng)圖像數(shù)據(jù)緩沖區(qū)");
return FALSE ;
}
memcpy(pData1,pData,WIDTHBYTES(Width*8)*Height);
for(i=10;i<Height-10;i++)
for(j=32;j<Width-32;j++)
{
bDilation=FALSE;
sum=*(pData+WIDTHBYTES(Width*8)*i+j);
if(sum==0)
{
//求像素點(diǎn)八鄰域的灰度值,;
for(m=-1;m<2;m++)
{
for(n=-1;n<2;n++)
{
sum1=*(pData+WIDTHBYTES(Width*8)*(i+m)+j+n);
if(sum1==255)
{
*(pData1+WIDTHBYTES(Width*8)*i+j)=255;
bDilation=TRUE;
break;
}
}
if(bDilation)
{
bDilation=FALSE;
break;
}
}
}
}
memcpy(pData,pData1,WIDTHBYTES(Width*8)*Height);
return TRUE;
} |
從上面的說明可以看出,腐蝕可以消除圖像中小的噪聲區(qū)域,,膨脹可以填補(bǔ)物體中的空洞,。對(duì)一個(gè)圖像先進(jìn)行腐蝕運(yùn)算然后再膨脹的操作過程稱為開運(yùn)算,它可以消除細(xì)小的物體,、在纖細(xì)點(diǎn)處分離物體,、平滑較大物體的邊界時(shí)不明顯的改變其面積。如果對(duì)一個(gè)圖像先膨脹然后再收縮,,我們稱之為閉運(yùn)算,,它具有填充物體內(nèi)細(xì)小的空洞、連接鄰近物體,、在不明顯改變物體面積的情況下平滑其邊界的作用,。通常情況下,當(dāng)有噪聲的圖像用閾值二值化后,,所得到的邊界是很不平滑的,,物體區(qū)域具有一些錯(cuò)判的孔洞,背景區(qū)域散布著一些小的噪聲物體,,連續(xù)的開和閉運(yùn)算可以顯著的改善這種情況,,這時(shí)候需要在連接幾次腐蝕迭代之后,再加上相同次數(shù)的膨脹,,才可以產(chǎn)生所期望的效果,。為了更好的顯示出二值圖像的處理效果,我們?nèi)耘f以圖像采集卡獲取的汽車圖像為處理源圖像,,下圖為處理后的效果:
(a)噪聲圖 |
(b)開運(yùn)算處理 |
圖一 開運(yùn)算效果圖
上圖中,,a圖為包含噪聲的圖像,b圖為經(jīng)過腐蝕膨脹處理后的圖像,,可以看出,,經(jīng)過上述處理,成功的消除了圖像中的噪聲點(diǎn),同時(shí)又起到了平滑邊緣的作用,。
|