




已閱讀5頁(yè),還剩21頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章 腐蝕,膨脹,細(xì)化算法這一章的內(nèi)容我認(rèn)為是最有趣的。還記得前言中那個(gè)抽取骨架的例子嗎?現(xiàn)在我們就來(lái)看看它是如何實(shí)現(xiàn)的。今天所講的內(nèi)容屬于一門(mén)新興的學(xué)科:數(shù)學(xué)形態(tài)學(xué)(Mathematical Morphology)。說(shuō)起來(lái)很有意思,它是法國(guó)和德國(guó)的科學(xué)家在研究巖石結(jié)構(gòu)時(shí)建立的一門(mén)學(xué)科。形態(tài)學(xué)的用途主要是獲取物體拓?fù)浜徒Y(jié)構(gòu)信息,它通過(guò)物體和結(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)、連通度、顆粒度、骨架和方向性等。限于篇幅,我們只介紹二值圖象的形態(tài)學(xué)運(yùn)算,對(duì)于灰度圖象的形態(tài)學(xué)運(yùn)算,有興趣的讀者可以閱讀有關(guān)的參考書(shū)。在程序中,為了處理的方便,還是采用256級(jí)灰度圖,不過(guò)只用到了調(diào)色板中的0和255兩項(xiàng)。先來(lái)定義一些基本符號(hào)和關(guān)系。1. 元素設(shè)有一幅圖象X,若點(diǎn)a在X的區(qū)域以內(nèi),則稱a為X的元素,記作aX,如圖6.1所示。2. B包含于X設(shè)有兩幅圖象B,X。對(duì)于B中所有的元素ai,都有aiX,則稱B包含于(included in)X,記作B X,如圖6.2所示。3. B擊中X設(shè)有兩幅圖象B,X。若存在這樣一個(gè)點(diǎn),它即是B的元素,又是X的元素,則稱B擊中(hit)X,記作BX,如圖6.3所示。4. B不擊中X設(shè)有兩幅圖象B,X。若不存在任何一個(gè)點(diǎn),它即是B的元素,又是X的元素,即B和X的交集是空,則稱B不擊中(miss)X,記作BX=;其中是集合運(yùn)算相交的符號(hào),表示空集。如圖6.4所示。圖6.1 元素圖6.2 包含圖6.3 擊中圖6.4 不擊中5. 補(bǔ)集設(shè)有一幅圖象X,所有X區(qū)域以外的點(diǎn)構(gòu)成的集合稱為X的補(bǔ)集,記作Xc,如圖6.5所示。顯然,如果BX=,則B在X的補(bǔ)集內(nèi),即B Xc。圖6.5 補(bǔ)集的示意圖6. 結(jié)構(gòu)元素設(shè)有兩幅圖象B,X。若X是被處理的對(duì)象,而B(niǎo)是用來(lái)處理X的,則稱B為結(jié)構(gòu)元素(structure element),又被形象地稱做刷子。結(jié)構(gòu)元素通常都是一些比較小的圖象。7. 對(duì)稱集設(shè)有一幅圖象B,將B中所有元素的坐標(biāo)取反,即令(x,y)變成(-x,-y),所有這些點(diǎn)構(gòu)成的新的集合稱為B的對(duì)稱集,記作Bv,如圖6.6所示。8. 平移設(shè)有一幅圖象B,有一個(gè)點(diǎn)a(x0,y0),將B平移a后的結(jié)果是,把B中所有元素的橫坐標(biāo)加x0,縱坐標(biāo)加y0,即令(x,y)變成(x+x0,y+y0),所有這些點(diǎn)構(gòu)成的新的集合稱為B的平移,記作Ba,如圖6.7所示。圖6.6 對(duì)稱集的示意圖圖6.7 平移的示意圖好了,介紹了這么多基本符號(hào)和關(guān)系,現(xiàn)在讓我們應(yīng)用這些符號(hào)和關(guān)系,看一下形態(tài)學(xué)的基本運(yùn)算。6.1 腐蝕把結(jié)構(gòu)元素B平移a后得到Ba,若Ba包含于X,我們記下這個(gè)a點(diǎn),所有滿足上述條件的a點(diǎn)組成的集合稱做X被B腐蝕(Erosion)的結(jié)果。用公式表示為:E(X)=a| Ba X=X B,如圖6.8所示。圖6.8 腐蝕的示意圖圖6.8中X是被處理的對(duì)象,B是結(jié)構(gòu)元素。不難知道,對(duì)于任意一個(gè)在陰影部分的點(diǎn)a,Ba 包含于X,所以X被B腐蝕的結(jié)果就是那個(gè)陰影部分。陰影部分在X的范圍之內(nèi),且比X小,就象X被剝掉了一層似的,這就是為什么叫腐蝕的原因。值得注意的是,上面的B是對(duì)稱的,即B的對(duì)稱集Bv=B,所以X被B腐蝕的結(jié)果和X被 Bv腐蝕的結(jié)果是一樣的。如果B不是對(duì)稱的,讓我們看看圖6.9,就會(huì)發(fā)現(xiàn)X被B腐蝕的結(jié)果和X被 Bv腐蝕的結(jié)果不同。圖6.9 結(jié)構(gòu)元素非對(duì)稱時(shí),腐蝕的結(jié)果不同圖6.8和圖6.9都是示意圖,讓我們來(lái)看看實(shí)際上是怎樣進(jìn)行腐蝕運(yùn)算的。在圖6.10中,左邊是被處理的圖象X(二值圖象,我們針對(duì)的是黑點(diǎn)),中間是結(jié)構(gòu)元素B,那個(gè)標(biāo)有origin的點(diǎn)是中心點(diǎn),即當(dāng)前處理元素的位置,我們?cè)诮榻B模板操作時(shí)也有過(guò)類似的概念。腐蝕的方法是,拿B的中心點(diǎn)和X上的點(diǎn)一個(gè)一個(gè)地對(duì)比,如果B上的所有點(diǎn)都在X的范圍內(nèi),則該點(diǎn)保留,否則將該點(diǎn)去掉;右邊是腐蝕后的結(jié)果。可以看出,它仍在原來(lái)X的范圍內(nèi),且比X包含的點(diǎn)要少,就象X被腐蝕掉了一層。圖6.10 腐蝕運(yùn)算圖6.11為原圖,圖6.12為腐蝕后的結(jié)果圖,能夠很明顯地看出腐蝕的效果。圖6.11 原圖圖6.12 腐蝕后的結(jié)果圖下面的這段程序,實(shí)現(xiàn)了上述的腐蝕運(yùn)算,針對(duì)的都是黑色點(diǎn)。參數(shù)中有一個(gè)BOOL變量,為真時(shí),表示在水平方向進(jìn)行腐蝕運(yùn)算,即結(jié)構(gòu)元素B為 ;否則在垂直方向上進(jìn)行腐蝕運(yùn)算,即結(jié)構(gòu)元素B為 。BOOL Erosion(HWND hWnd,BOOL Hori) DWORD OffBits,BufSize;LPBITMAPINFOHEADER lpImgData; LPSTR lpPtr; HLOCAL hTempImgData; LPBITMAPINFOHEADER lpTempImgData; LPSTR lpTempPtr; HDC hDc; HFILE hf; LONG x,y; unsigned char num; int i;/為了處理方便,仍采用256級(jí)灰度圖,不過(guò)只用調(diào)色板中0和255兩項(xiàng)if( NumColors!=256) MessageBox(hWnd,Must be a mono bitmap with grayscale palette!,Error Message,MB_OK|MB_ICONEXCLAMATION);return FALSE;OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);/BufSize為緩沖區(qū)大小 BufSize=OffBits+bi.biHeight*LineBytes; /為新的緩沖區(qū)分配內(nèi)存 if(hTempImgData=LocalAlloc(LHND,BufSize)=NULL) MessageBox(hWnd,Error alloc memory!,Error Message,MB_OK|MB_ICONEXCLAMATION);return FALSE; lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData); lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); /拷貝頭信息和位圖數(shù)據(jù) memcpy(lpTempImgData,lpImgData,BufSize); if(Hori) /在水平方向進(jìn)行腐蝕運(yùn)算 for(y=0;ybi.biHeight;y+) /lpPtr指向原圖數(shù)據(jù),lpTempPtr指向新圖數(shù)據(jù) lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+1; lpTempPtr=(char*)lpTempImgData+(BufSize-LineBytes-y*LineBytes)+1; for(x=1;xbi.biWidth-1;x+) /注意為防止越界,x的范圍從1到寬度-2 num=(unsigned char)*lpPtr; if (num=0) /因?yàn)楦g掉的是黑點(diǎn),所以只對(duì)黑點(diǎn)處理 *lpTempPtr=(unsigned char)0; /先置成黑點(diǎn) for(i=0;i3;i+) num=(unsigned char)*(lpPtr+i-1); if(num=255) /自身及上下鄰居中若有一個(gè)不是黑點(diǎn),則將該點(diǎn)腐/蝕成白點(diǎn) *lpTempPtr=(unsigned char)255; break; /原圖中就是白點(diǎn)的,新圖中仍是白點(diǎn) else *lpTempPtr=(unsigned char)255; /指向下一個(gè)象素 lpPtr+; lpTempPtr+; else /在垂直方向進(jìn)行腐蝕運(yùn)算 for(y=1;ybi.biHeight-1;y+) /注意為防止越界,y的范圍從1到高度-2 /lpPtr指向原圖數(shù)據(jù),lpTempPtr指向新圖數(shù)據(jù) lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes); for(x=0;xbi.biWidth;x+) num=(unsigned char)*lpPtr; if (num=0) /因?yàn)楦g掉的是黑點(diǎn),所以只對(duì)黑點(diǎn)處理 *lpTempPtr=(unsigned char)0; /先置成黑點(diǎn) for(i=0;i3;i+) num=(unsigned char)*(lpPtr+(i-1)*LineBytes); if(num=255)/自身及上下鄰居中若有一個(gè)不是黑點(diǎn),則將該點(diǎn)腐/蝕成白點(diǎn) *lpTempPtr=(unsigned char)255; break; /原圖中就是白點(diǎn)的,新圖中仍是白點(diǎn) else *lpTempPtr=(unsigned char)255; /指向下一個(gè)象素 lpPtr+; lpTempPtr+; if(hBitmap!=NULL) DeleteObject(hBitmap); hDc=GetDC(hWnd); /產(chǎn)生新的位圖 hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,(LONG)CBM_INIT,(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER)+ NumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS); /起不同的結(jié)果文件名 if(Hori) hf=_lcreat(c:herosion.bmp,0); else hf=_lcreat(c:verosion.bmp,0); _lwrite(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER); _lwrite(hf,(LPSTR)lpTempImgData,BufSize); _lclose(hf); /釋放內(nèi)存及資源ReleaseDC(hWnd,hDc); LocalUnlock(hTempImgData); LocalFree(hTempImgData); GlobalUnlock(hImgData); return TRUE;6.2 膨脹膨脹(dilation)可以看做是腐蝕的對(duì)偶運(yùn)算,其定義是:把結(jié)構(gòu)元素B平移a后得到Ba,若Ba擊中X,我們記下這個(gè)a點(diǎn)。所有滿足上述條件的a點(diǎn)組成的集合稱做X被B膨脹的結(jié)果。用公式表示為:D(X)=a | BaX=X B,如圖6.13所示。圖6.13中X是被處理的對(duì)象,B是結(jié)構(gòu)元素,不難知道,對(duì)于任意一個(gè)在陰影部分的點(diǎn)a,Ba擊中X,所以X被B膨脹的結(jié)果就是那個(gè)陰影部分。陰影部分包括X的所有范圍,就象X膨脹了一圈似的,這就是為什么叫膨脹的原因。同樣,如果B不是對(duì)稱的,X被B膨脹的結(jié)果和X被 Bv膨脹的結(jié)果不同。讓我們來(lái)看看實(shí)際上是怎樣進(jìn)行膨脹運(yùn)算的。在圖6.14中,左邊是被處理的圖象X(二值圖象,我們針對(duì)的是黑點(diǎn)),中間是結(jié)構(gòu)元素B。膨脹的方法是,拿B的中心點(diǎn)和X上的點(diǎn)及X周圍的點(diǎn)一個(gè)一個(gè)地對(duì),如果B上有一個(gè)點(diǎn)落在X的范圍內(nèi),則該點(diǎn)就為黑;右邊是膨脹后的結(jié)果??梢钥闯?,它包括X的所有范圍,就象X膨脹了一圈似的。圖6.13 膨脹的示意圖圖6.14 膨脹運(yùn)算圖6.15為圖6.11膨脹后的結(jié)果圖,能夠很明顯的看出膨脹的效果。圖6.15 圖6.11膨脹后的結(jié)果圖下面的這段程序,實(shí)現(xiàn)了上述的膨脹運(yùn)算,針對(duì)的都是黑色點(diǎn)。參數(shù)中有一個(gè)BOOL變量,為真時(shí),表示在水平方向進(jìn)行膨脹運(yùn)算,即結(jié)構(gòu)元素B為 ;否則在垂直方向上進(jìn)行膨脹運(yùn)算,即結(jié)構(gòu)元素B為 。BOOL Dilation(HWND hWnd,BOOL Hori) DWORD OffBits,BufSize;LPBITMAPINFOHEADER lpImgData; LPSTR lpPtr; HLOCAL hTempImgData; LPBITMAPINFOHEADER lpTempImgData; LPSTR lpTempPtr; HDC hDc; HFILE hf; LONG x,y; unsigned char num; int i;/為了處理的方便,仍采用256級(jí)灰度圖,不過(guò)只調(diào)色板中0和255兩項(xiàng)if( NumColors!=256) MessageBox(hWnd,Must be a mono bitmap with grayscale palette!,Error Message,MB_OK|MB_ICONEXCLAMATION);return FALSE;OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);/BufSize為緩沖區(qū)大小 BufSize=OffBits+bi.biHeight*LineBytes;/為新的緩沖區(qū)分配內(nèi)存 if(hTempImgData=LocalAlloc(LHND,BufSize)=NULL) MessageBox(hWnd,Error alloc memory!,Error Message,MB_OK|MB_ICONEXCLAMATION);return FALSE; lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData); lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); /拷貝頭信息和位圖數(shù)據(jù) memcpy(lpTempImgData,lpImgData,BufSize); if(Hori) /在水平方向進(jìn)行膨脹運(yùn)算 for(y=0;ybi.biHeight;y+) /lpPtr指向原圖數(shù)據(jù),lpTempPtr指向新圖數(shù)據(jù) lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+1; lpTempPtr=(char*)lpTempImgData+(BufSize-LineBytes-y*LineBytes)+1; for(x=1;xbi.biWidth-1;x+) /注意為防止越界,x的范圍從1到寬度-2 num=(unsigned char)*lpPtr;/原圖中是黑點(diǎn)的,新圖中肯定也是,所以要考慮的是那些原圖/中的白點(diǎn),看是否有可能膨脹成黑點(diǎn) if (num=255) *lpTempPtr=(unsigned char)255; /先置成白點(diǎn) for(i=0;i3;i+) num=(unsigned char)*(lpPtr+i-1);/只要左右鄰居中有一個(gè)是黑點(diǎn),就膨脹成黑點(diǎn) if(num=0)*lpTempPtr=(unsigned char)0; break; /原圖中就是黑點(diǎn)的,新圖中仍是黑點(diǎn) else *lpTempPtr=(unsigned char)0; /指向下一個(gè)象素 lpPtr+; lpTempPtr+; else/在垂直方向進(jìn)行腐蝕運(yùn)算 for(y=1;ybi.biHeight-1;y+) /注意為防止越界,y的范圍從1到高度-2 lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes); for(x=0;xbi.biWidth;x+) num=(unsigned char)*lpPtr; if (num=255) *lpTempPtr=(unsigned char)255; for(i=0;i3;i+) num=(unsigned char)*(lpPtr+(i-1)*LineBytes);/只要上下鄰居中有一個(gè)是黑點(diǎn),就膨脹成黑點(diǎn) if(num=0) *lpTempPtr=(unsigned char)0; break; else *lpTempPtr=(unsigned char)0; lpPtr+; lpTempPtr+; if(hBitmap!=NULL) DeleteObject(hBitmap); hDc=GetDC(hWnd); /產(chǎn)生新的位圖 hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,(LONG)CBM_INIT,(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER)+ NumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpTempImgData,DIB_RGB_COLORS); /起不同的結(jié)果文件名 if(Hori) hf=_lcreat(c:hdilation.bmp,0); else hf=_lcreat(c:vdilation.bmp,0); _lwrite(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER); _lwrite(hf,(LPSTR)lpTempImgData,BufSize); _lclose(hf); /釋放內(nèi)存及資源 ReleaseDC(hWnd,hDc); LocalUnlock(hTempImgData); LocalFree(hTempImgData); GlobalUnlock(hImgData); return TRUE;腐蝕運(yùn)算和膨脹運(yùn)算互為對(duì)偶的,用公式表示為(X B)c=(Xc B),即X 被B腐蝕后的補(bǔ)集等于X的補(bǔ)集被B膨脹。這句話可以形象的理解為:河岸的補(bǔ)集為河面,河岸的腐蝕等價(jià)于河面的膨脹。你可以自己舉個(gè)例子來(lái)驗(yàn)證一下這個(gè)關(guān)系。在有些情況下,這個(gè)對(duì)偶關(guān)系是非常有用的。例如:某個(gè)圖象處理系統(tǒng)用硬件實(shí)現(xiàn)了腐蝕運(yùn)算,那么不必再另搞一套膨脹的硬件,直接利用該對(duì)偶就可以實(shí)現(xiàn)了。6.3 開(kāi)先腐蝕后膨脹稱為開(kāi)(open),即OPEN(X)=D(E(X)。讓我們來(lái)看一個(gè)開(kāi)運(yùn)算的例子(見(jiàn)圖6.16):圖6.16開(kāi)運(yùn)算在圖16上面的兩幅圖中,左邊是被處理的圖象X(二值圖象,我們針對(duì)的是黑點(diǎn)),右邊是結(jié)構(gòu)元素B,下面的兩幅圖中左邊是腐蝕后的結(jié)果;右邊是在此基礎(chǔ)上膨脹的結(jié)果??梢钥吹剑瓐D經(jīng)過(guò)開(kāi)運(yùn)算后,一些孤立的小點(diǎn)被去掉了。一般來(lái)說(shuō),開(kāi)運(yùn)算能夠去除孤立的小點(diǎn),毛刺和小橋(即連通兩塊區(qū)域的小點(diǎn)),而總的位置和形狀不變。這就是開(kāi)運(yùn)算的作用。要注意的是,如果B是非對(duì)稱的,進(jìn)行開(kāi)運(yùn)算時(shí)要用B的對(duì)稱集Bv膨脹,否則,開(kāi)運(yùn)算的結(jié)果和原圖相比要發(fā)生平移。圖6.17和圖6.18能夠說(shuō)明這個(gè)問(wèn)題。圖6.17 用B膨脹后,結(jié)果向左平移了圖6.18 用Bv膨脹后位置不變圖6.17是用B膨脹的,可以看到,OPEN(X)向左平移了。圖18是用Bv膨脹的,可以看到,總的位置和形狀不變。圖6.19為圖6.11經(jīng)過(guò)開(kāi)運(yùn)算后的結(jié)果。圖6.19 圖6.11經(jīng)過(guò)開(kāi)運(yùn)算后的結(jié)果開(kāi)運(yùn)算的源程序可以很容易的根據(jù)上面的腐蝕,膨脹程序得到,這里就不給出了。6.4 閉先膨脹后腐蝕稱為閉(close),即CLOSE(X)=E(D(X)。讓我們來(lái)看一個(gè)閉運(yùn)算的例子(見(jiàn)圖6.20):圖6.20 閉運(yùn)算在圖6.20上面的兩幅圖中,左邊是被處理的圖象X(二值圖象,我們針對(duì)的是黑點(diǎn)),右邊是結(jié)構(gòu)元素B,下面的兩幅圖中左邊是膨脹后的結(jié)果,右邊是在此基礎(chǔ)上腐蝕的結(jié)果可以看到,原圖經(jīng)過(guò)閉運(yùn)算后,斷裂的地方被彌合了。一般來(lái)說(shuō),閉運(yùn)算能夠填平小湖(即小孔),彌合小裂縫,而總的位置和形狀不變。這就是閉運(yùn)算的作用。同樣要注意的是,如果B是非對(duì)稱的,進(jìn)行閉運(yùn)算時(shí)要用B的對(duì)稱集Bv膨脹,否則,閉運(yùn)算的結(jié)果和原圖相比要發(fā)生平移。圖6.21為圖6.11經(jīng)過(guò)閉運(yùn)算后的結(jié)果。圖6.21 圖.611經(jīng)過(guò)閉運(yùn)算后的結(jié)果閉運(yùn)算的源程序可以很容易的根據(jù)上面的膨脹,腐蝕程序得到,這里就不給出了。你大概已經(jīng)猜到了,開(kāi)和閉也是對(duì)偶運(yùn)算,的確如此。用公式表示為(OPEN(X)c=CLOSE(Xc),或者(CLOSE(X)c =OPEN(Xc)。即X 開(kāi)運(yùn)算的補(bǔ)集等于X的補(bǔ)集的閉運(yùn)算,或者X 閉運(yùn)算的補(bǔ)集等于X的補(bǔ)集的開(kāi)運(yùn)算。這句話可以這樣來(lái)理解:在兩個(gè)小島之間有一座小橋,我們把島和橋看做是處理對(duì)象X,則X的補(bǔ)集為大海。如果漲潮時(shí)將小橋和島的外圍淹沒(méi)(相當(dāng)于用尺寸比橋?qū)挻蟮慕Y(jié)構(gòu)元素對(duì)X進(jìn)行開(kāi)運(yùn)算),那么兩個(gè)島的分隔,相當(dāng)于小橋兩邊海域的連通(對(duì)Xc做閉運(yùn)算)。6.5 細(xì)化細(xì)化(thinning)算法有很多,我們?cè)谶@里介紹的是一種簡(jiǎn)單而且效果很好的算法,用它就能夠?qū)崿F(xiàn)從文本抽取骨架的功能。我們的對(duì)象是白紙黑字的文本,但在程序中為了處理的方便,還是采用256級(jí)灰度圖,不過(guò)只用到了調(diào)色板中0和255兩項(xiàng)。所謂細(xì)化,就是從原來(lái)的圖中去掉一些點(diǎn),但仍要保持原來(lái)的形狀。實(shí)際上,是保持原圖的骨架。所謂骨架,可以理解為圖象的中軸,例如一個(gè)長(zhǎng)方形的骨架是它的長(zhǎng)方向上的中軸線;正方形的骨架是它的中心點(diǎn);圓的骨架是它的圓心,直線的骨架是它自身,孤立點(diǎn)的骨架也是自身。文本的骨架嘛,前言中的例子顯示的很明白。那么怎樣判斷一個(gè)點(diǎn)是否能去掉呢?顯然,要根據(jù)它的八個(gè)相鄰點(diǎn)的情況來(lái)判斷,我們給幾個(gè)例子(如圖6.22所示)。圖6.22 根據(jù)某點(diǎn)的八個(gè)相鄰點(diǎn)的情況來(lái)判斷該點(diǎn)是否能刪除圖6.22中,(1)不能刪,因?yàn)樗莻€(gè)內(nèi)部點(diǎn),我們要求的是骨架,如果連內(nèi)部點(diǎn)也刪了,骨架也會(huì)被掏空的;(2)不能刪,和(1)是同樣的道理;(3)可以刪,這樣的點(diǎn)不是骨架;(4)不能刪,因?yàn)閯h掉后,原來(lái)相連的部分?jǐn)嚅_(kāi)了;(5)可以刪,這樣的點(diǎn)不是骨架;(6)不能刪,因?yàn)樗侵本€的端點(diǎn),如果這樣的點(diǎn)刪了,那么最后整個(gè)直線也被刪了,剩不下什么;(7)不能刪,因?yàn)楣铝Ⅻc(diǎn)的骨架就是它自身??偨Y(jié)一下,有如下的判據(jù):(1)內(nèi)部點(diǎn)不能刪除;(2)孤立點(diǎn)不能刪除;(3)直線端點(diǎn)不能刪除;(4)如果P是邊界點(diǎn),去掉P后,如果連通分量不增加,則P可以刪除。我們可以根據(jù)上述的判據(jù),事先做出一張表,從0到255共有256個(gè)元素,每個(gè)元素要么是0,要么是1。我們根據(jù)某點(diǎn)(當(dāng)然是要處理的黑色點(diǎn)了)的八個(gè)相鄰點(diǎn)的情況查表,若表中的元素是1,則表示該點(diǎn)可刪,否則保留。查表的方法是,設(shè)白點(diǎn)為1,黑點(diǎn)為0;左上方點(diǎn)對(duì)應(yīng)一個(gè)8位數(shù)的第一位(最低位),正上方點(diǎn)對(duì)應(yīng)第二位,右上方點(diǎn)對(duì)應(yīng)的第三位,左鄰點(diǎn)對(duì)應(yīng)第四位,右鄰點(diǎn)對(duì)應(yīng)第五位,左下方點(diǎn)對(duì)應(yīng)第六位,正下方點(diǎn)對(duì)應(yīng)第七位,右下方點(diǎn)對(duì)應(yīng)的第八位,按這樣組成的8位數(shù)去查表即可。例如上面的例子中(1)對(duì)應(yīng)表中的第0項(xiàng),該項(xiàng)應(yīng)該為0;(2)對(duì)應(yīng)37,該項(xiàng)應(yīng)該為0;(3)對(duì)應(yīng)173,該項(xiàng)應(yīng)該為1;(4)對(duì)應(yīng)231,該項(xiàng)應(yīng)該為0;(5)對(duì)應(yīng)237,該項(xiàng)應(yīng)該為1;(6)對(duì)應(yīng)254,該項(xiàng)應(yīng)該為0;(7)對(duì)應(yīng)255,該項(xiàng)應(yīng)該為0。這張表我已經(jīng)替大家做好了,可花了我不少時(shí)間呢!static int erasetable256= 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1, 1,1,0,0,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,0,0, 1,1,0,1,1,1,0,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0, 1,1,0,0,1,1,0,0, 1,1,0,1,1,1,0,0, 1,1,0,0,1,1,1,0, 1,1,0,0,1,0,0,0 ;有了這張表,算法就很簡(jiǎn)單了,每次對(duì)一行一行的將整個(gè)圖象掃描一遍,對(duì)于每個(gè)點(diǎn)(不包括邊界點(diǎn)),計(jì)算它在表中對(duì)應(yīng)的索引,若為0,則保留,否則刪除該點(diǎn)。如果這次掃描沒(méi)有一個(gè)點(diǎn)被刪除,則循環(huán)結(jié)束,剩下的點(diǎn)就是骨架點(diǎn),如果有點(diǎn)被刪除,則進(jìn)行新的一輪掃描,如此反復(fù),直到?jīng)]有點(diǎn)被刪除為止。實(shí)際上,該算法有一些缺陷。舉個(gè)簡(jiǎn)單的例子,有一個(gè)黑色矩形,如圖6.23所示。圖6.23經(jīng)過(guò)細(xì)化后,我們預(yù)期的結(jié)果是一條水平直線,且位于該黑色矩形的中心。實(shí)際的結(jié)果確實(shí)是一條水平直線,但不是位于黑色矩形的中心,而是最下面的一條邊。為什么會(huì)這樣,我們來(lái)分析一下:在從上到下,從左到右的掃描過(guò)程中,我們遇到的第一個(gè)黑點(diǎn)就是黑色矩形的左上角點(diǎn),經(jīng)查表,該點(diǎn)可以刪。下一個(gè)點(diǎn)是它右邊的點(diǎn),經(jīng)查表,該點(diǎn)也可以刪,如此下去,整個(gè)一行被刪了。每一行都是同樣的情況,所以都被刪除了。到了最后一行時(shí),黑色矩形已經(jīng)變成了一條直線,最左邊的黑點(diǎn)不能刪,因?yàn)樗侵本€的端點(diǎn),它右邊的點(diǎn)也不能刪,因?yàn)槿绻麆h除,直線就斷了,如此下去,直到最右邊的點(diǎn),也不能刪,因?yàn)樗侵本€的右端點(diǎn)。所以最下面的一條邊保住了,但這并不是我們希望的結(jié)果。解決的辦法是,在每一行水平掃描的過(guò)程中,先判斷每一點(diǎn)的左右鄰居,如果都是黑點(diǎn),則該點(diǎn)不做處理。另外,如果某個(gè)黑點(diǎn)被刪除了,那么跳過(guò)它的右鄰居,處理下一個(gè)點(diǎn)。這樣就避免了上述的問(wèn)題。圖6.23 黑色矩形圖6.24 圖6.23細(xì)化后的結(jié)果解決了上面的問(wèn)題,我們來(lái)看看處理后的結(jié)果,如圖6.24所示。這次變成一小段豎線了,還是不對(duì),是不是很沮喪?別著急,讓我們?cè)賮?lái)分析一下:在上面的算法中,我們遇到的第一個(gè)能刪除的點(diǎn)就是黑色矩形的左上角點(diǎn);第二個(gè)是第一行的最右邊的點(diǎn),即黑色矩形的右上角點(diǎn);第三個(gè)是第二行的最左邊的點(diǎn);第四個(gè)是第二行的最右邊的點(diǎn);整個(gè)圖象處理這樣一次后,寬度減少2。每次都是如此,直到剩最中間一列,就不能再刪了。為什么會(huì)這樣呢?原因是這樣的處理過(guò)程只實(shí)現(xiàn)了水平細(xì)化,如果在每一次水平細(xì)化后,再進(jìn)行一次垂直方向的細(xì)化(只要把上述過(guò)程的行列換一下),就可以了。這樣一來(lái),每處理一次,刪除點(diǎn)的順序變成:(先是水平方向掃描)第一行最左邊的點(diǎn);第一行最右邊的點(diǎn);第二行最左邊的點(diǎn);第二行最右邊的點(diǎn);最后一行最左邊的點(diǎn);最后一行最右邊的點(diǎn);(然后是垂直方向掃描)第二列最上邊的點(diǎn)(因?yàn)榈谝涣凶钌线叺狞c(diǎn)已被刪除);第二列最下邊的點(diǎn);第三列最上邊的點(diǎn);第三列最下邊的點(diǎn);倒數(shù)第二列最上邊的點(diǎn)(因?yàn)榈箶?shù)第一列最上邊的點(diǎn)已被刪除);倒數(shù)第二列最下邊的點(diǎn)。我們發(fā)現(xiàn),剛好剝掉了一圈,這也正是細(xì)化要做的事。實(shí)際的結(jié)果也驗(yàn)證了我們的想法。以下是源程序,黑體字部分是值得注意的地方。BOOL Thinning(HWND hWnd) DWORD OffBits,BufSize; LPBITMAPINFOHEADER lpImgData; LPSTR lpPtr; HLOCAL hTempImgData; LPBITMAPINFOHEADER lpTempImgData; LPSTR lpTempPtr; HDC hDc; HFILE hf; LONG x,y; int num; BOOL Finished; int nw,n,ne,w,e,sw,s,se;/為了處理的方便,仍采用256級(jí)灰度圖,不過(guò)只用調(diào)色板中0和255兩項(xiàng) if( NumColors!=256)MessageBox(hWnd,Must be a mono bitmap with grayscale palette!,Error Message,MB_OK|MB_ICONEXCLAMATION);return FALSE;OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);/BufSize為緩沖區(qū)大小 BufSize=OffBits+bi.biHeight*
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年房地產(chǎn)投資分析師資格考試試卷及答案
- 小動(dòng)物的冒險(xiǎn)故事童話故事11篇
- 傳承文化走進(jìn)民間藝術(shù)展覽話題6篇
- 電商平臺(tái)技術(shù)升級(jí)與服務(wù)協(xié)議
- 語(yǔ)言學(xué)概論中的語(yǔ)言與文化關(guān)系研究試題
- 2025年陰極銅項(xiàng)目申請(qǐng)報(bào)告
- 云朵上的奇思妙想童話作文(9篇)
- 2025年輔導(dǎo)員職位選拔考試:學(xué)生活動(dòng)策劃與活動(dòng)策劃效果評(píng)估案例分析試題
- 2025年度企業(yè)人力資源管理師(研究員)技能操作試題詳解
- 旅游目的地開(kāi)發(fā)及推廣合作協(xié)議
- 保定一中1+3物理試卷
- 明德云學(xué)堂義務(wù)教育心得
- 珍愛(ài)生命中學(xué)生心理健康主題班會(huì)
- Cmk設(shè)備能力指數(shù)分析表
- J17J177 鋼絲網(wǎng)架珍珠巖復(fù)合保溫外墻板建筑構(gòu)造
- 水泥檢測(cè)培訓(xùn)試題(附答案)
- 高標(biāo)準(zhǔn)農(nóng)田建設(shè)上圖入庫(kù)(技術(shù)培訓(xùn))
- 四川省2020年普通高中學(xué)業(yè)水平考試通用技術(shù)試題及答案
- 膽囊結(jié)石伴膽囊炎演示文稿
- 一、高等分離工程-01-緒論2011
- 浙江省環(huán)境監(jiān)測(cè)中心質(zhì)量手冊(cè)
評(píng)論
0/150
提交評(píng)論