




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第6章腐蝕,膨脹,細(xì)化算法這一章的內(nèi)容我認(rèn)為是最有趣的。還記得前言中那個(gè)抽取骨架的例子嗎?現(xiàn)在我們就來看看它是如何實(shí)現(xiàn)的。今天所講的內(nèi)容屬于一門新興的學(xué)科:數(shù)學(xué)形態(tài)學(xué)(Mathematical Morphology)。說起來很有意思,它是法國和德國的科學(xué)家在研究巖石結(jié)構(gòu)時(shí)建立的一門學(xué)科。形態(tài)學(xué)的用途主要是獲取物體拓?fù)浜徒Y(jié)構(gòu)信息,它通過物體和結(jié)構(gòu)元素相互作用的某些運(yùn)算,得到物體更本質(zhì)的形態(tài)。在圖象處理中的應(yīng)用主要是:(1)利用形態(tài)學(xué)的根本運(yùn)算,對(duì)圖象進(jìn)行觀察和處理,從而到達(dá)改善圖象質(zhì)量的目的;(2)描述和定義圖象的各種幾何參數(shù)和特征,如面積、周長、連通度、顆粒度、骨架和方向性等。限于篇幅,我們只
2、介紹二值圖象的形態(tài)學(xué)運(yùn)算,對(duì)于灰度圖象的形態(tài)學(xué)運(yùn)算,有興趣的讀者可以閱讀有關(guān)的參考書。在程序中,為了處理的方便,還是采用256級(jí)灰度圖,不過只用到了調(diào)色板中的0和255兩項(xiàng)。先來定義一些根本符號(hào)和關(guān)系。1.1.元素設(shè)有一幅圖象X,假設(shè)點(diǎn)a在X的區(qū)域以內(nèi),那么稱a為X的元素,記作a X,如圖6.1所示。2.2.B B包含于X X設(shè)有兩幅圖象B, X。對(duì)于B中所有的元素ai,都有ai C X ,那么稱B包含于(included in)X,記作BUX,如圖6.2所 示。3.3.B B擊中X X設(shè)有兩幅圖象B, X。假設(shè)存在這樣一個(gè)點(diǎn),它即是B的元素,又是X的元素,那么稱B擊中(hit)X,記作Bf
3、X,如圖6.3所示。4.4.B B不擊中X X設(shè)有兩幅圖象B, X。假設(shè)不存在任何一個(gè)點(diǎn),它即是B的元素,又是X的元素,即B和X的交集是空,那么稱B不擊 中(miss)X,記作B n X=中;其中口是集合運(yùn)算相交的符號(hào),中表示空集。如圖6.4所示。圖6.26.2包含5.5.補(bǔ)集設(shè)有一幅圖象X,所有X區(qū)域以外的點(diǎn)構(gòu)成的集合稱為X的補(bǔ)集,記作Xc,如圖6.5所示。顯然,如果B nX=中,那么B在X的補(bǔ)集內(nèi),即B UXc。圖6.56.5補(bǔ)集的示意圖6.6.結(jié)構(gòu)元素 設(shè)有兩幅圖象B, X。假設(shè)X是被處理的對(duì)象,而B是用來處理X的,那么稱B為結(jié)構(gòu)元素(structure element),又被形 象地稱
4、做刷子。結(jié)構(gòu)元素通常都是一些比擬小的圖象。7.7.對(duì)稱集設(shè)有一幅圖象B,將B中所有元素的坐標(biāo)取反,即令(x, y)變成(-x, -y),所有這些點(diǎn)構(gòu)成的新的集合稱為B的對(duì)稱集,記作Bv,如圖6.6所示。8.8.平移設(shè)有一幅圖象B,有一個(gè)點(diǎn)a(X0,y0),將B平移a后的結(jié)果是,把B中所有元素的橫坐標(biāo)加X0,縱坐標(biāo)加y0,即令(x,y)變成(x+x0,y+y。),所有這些點(diǎn)構(gòu)成的新的集合稱為B的平移,記作Ba,如圖6.7所示。好了,介紹了這么多根本符號(hào)和關(guān)系,現(xiàn)在讓我們應(yīng)用這些符號(hào)和關(guān)系,看一下形態(tài)學(xué)的根本運(yùn)算。6.1腐蝕圖6.36.3擊中圖6.46.4不擊中圖6.66.6對(duì)稱集的示意圖圖6.7
5、6.7平移的示意圖把結(jié)構(gòu)元素B平移a后得到Ba,假設(shè)Ba包含于X ,我們記下這個(gè)a點(diǎn),所有滿足上述條件的a點(diǎn)組成的集合稱做X被B腐蝕(Erosion)的結(jié)果。用公式表示為:E(X)=(a| BaC X=X B ,如圖6.8所示。圖6.86.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、讓我們看看圖6.9,就會(huì)發(fā)現(xiàn)X被B腐蝕的結(jié)果和X被Bv腐蝕的結(jié)果不同。圖6.96.9結(jié)構(gòu)元素非對(duì)稱時(shí),腐蝕的結(jié)果不同圖6.8和圖6.9都是示意圖,讓我們來看看實(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)前處理元素的位置,我們在介紹模板操作時(shí)也有過類似的概念。腐蝕的方法是,拿B的中心點(diǎn)和X上的點(diǎn)一個(gè)一個(gè)地比照,如果B上的所有點(diǎn)都在X的范圍內(nèi),那么該點(diǎn)保存,否那么將該點(diǎn)去掉;右邊是腐蝕后的結(jié)果。可 以看出,它仍在原來X的范圍內(nèi),且比X包含的點(diǎn)要少,就象X被腐蝕掉了一層。圖6.106.10腐
7、蝕運(yùn)算圖6.11為原圖,圖6.12為腐蝕后的結(jié)果圖,能夠很明顯地看出腐蝕的效果。Hi,Pm phoenix Glad tomeet u 圖6.116.11原圖phoenix Glad to meet u.圖6.126.12腐蝕后的結(jié)果圖卜面的這段程序,實(shí)現(xiàn)了上述的腐蝕運(yùn)算,針對(duì)的都是黑色點(diǎn)。參數(shù)中有一個(gè)BOOL變量,為真時(shí),表示在水平方向進(jìn)行腐蝕運(yùn)算,即結(jié)構(gòu)元素B為h L 1.;否那么在垂直方向上進(jìn)行腐蝕運(yùn)算,即結(jié)構(gòu)元素B為BOOL Erosion(HWND hWnd,BOOL Hori)(DWORDOffBits,BufSize;LPBITMAPINFOHEADERlpImgData;LPS
8、TRHLOCALhTempImgData;LPBITMAPINFOHEADERlpTempImgData;LPSTRlpTempPtr;HDChDc;HFILEhf;LONGx,y;unsigned charnum;inti;為了處理方便,仍采用256級(jí)灰度圖,不過只用調(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.bfOffBit
9、s-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;IpPtr;*lpTempPtr=(unsigned char)255;lpImgData=(LPBITMAPINFOHEADER)GlobalLoc
10、k(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-
11、y*LineBytes)+1;for(x=1;xbi.biWidth-1;x+)注意為防止越界,x的范圍從1到寬度-2num=(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)自身及上下鄰居中假設(shè)有一個(gè)不是黑點(diǎn),那么將該點(diǎn)腐 蝕成白點(diǎn)sizeof(BITMAPINFOHEADER)+break;/原圖中就是白點(diǎn)的,新圖中仍是白點(diǎn)else *lpTempPtr=(uns
12、igned 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;
13、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)(/自身及上下鄰居中假設(shè)有一個(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)Delete
14、Object(hBitmap);hDc=GetDC(hWnd);產(chǎn)生新的位圖hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,(LONG)CBM_INIT,(LPSTR)lpTempImgData+NumColors*sizeof(RGBQUAD),sizeof(BITMAPINFOHEADER)+(LPBITMAPINFO)lpTempImgData, D舊_RGB_COLORS);起不同的結(jié)果文件名if(Hori)hf=_lcreat(c:herosion.bmp,0);elsehf=_lcreat(c:verosio
15、n.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,假設(shè)Ba擊中X,我們記下這個(gè)a點(diǎn)。所有滿足上述條件
16、的a點(diǎn)組成的集合稱做X被B膨脹的結(jié)果。用公式表示為:D(X)=a | Baf X=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é)果不同。讓我們來看看實(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),
17、那么該點(diǎn)就為黑;右邊是膨脹后的結(jié)果。可以看出,它包括X的所有范圍,就象X膨脹了一圈似的。圖6.136.13膨脹的示意圖圖6.146.14膨脹運(yùn)算圖6.15為圖6.11膨脹后的結(jié)果圖,能夠很明顯的看出膨脹的效果。Hijm phoenix.Glad to meet u.圖6.156.15圖6.116.11膨脹后的結(jié)果圖下面的這段程序,實(shí)現(xiàn)了上述的膨脹運(yùn)算,針對(duì)的都是黑色點(diǎn)。參數(shù)中有一個(gè)BOOL變量,為真時(shí),表示在水平方1.向進(jìn)行膨脹運(yùn)算,即結(jié)構(gòu)元素B為1 1. 1;否那么在垂直方向上進(jìn)行膨脹運(yùn)算,即結(jié)構(gòu)元素B為1.。BOOL Dilation(HWND hWnd,BOOL Hori) (DWORD
18、OffBits,BufSize;LPBITMAPINFOHEADER lpImgData;LPSTRlpPtr;HLOCALhTempImgData;LPBITMAPINFOHEADER lpTempImgData;LPSTRlpTempPtr;HDChDc;HFILEhf;LONGx,y;unsigned charnum;inti;為了處理的方便,仍采用256級(jí)灰度圖,不過只調(diào)色板中0和255兩項(xiàng)if( NumColors!=256)MessageBox(hWnd,Must be a mono bitmap with grayscale palette!,Error Message,MB_O
19、K|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=(LPBITMAPINF
20、OHEADER)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+(B
21、ufSize-LineBytes-y*LineBytes)+1;for(x=1;xbi.biWidth-1;x+)注意為防止越界,x的范圍從1到寬度-2num=(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
22、)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到高度-2lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes);for(x=0;xbi.biWidth;x+)(num=(un
23、signed char)*lpPtr;if (num=255)*lpTempPtr=(unsigned char)255;for(i=0;i(3(5)(5)(6)(6)圖6.226.22根據(jù)某點(diǎn)的八個(gè)相鄰點(diǎn)的情況來判斷該點(diǎn)是否能刪除圖6.22中,1不能刪,因?yàn)樗莻€(gè)內(nèi)部點(diǎn),我們要求的是骨架,如果連內(nèi)部點(diǎn)也刪了,骨架也會(huì)被掏空的;2不能刪,和1是同樣的道理;3可以刪,這樣的點(diǎn)不是骨架;不能刪,因?yàn)閯h掉后,原來相連的局部斷開了;5可以刪,這樣的點(diǎn)不是骨架;6不能刪,因?yàn)樗侵本€的端點(diǎn),如果這樣的點(diǎn)刪了,那么最后整個(gè)直線也被刪了,剩不下什么;7不能刪,因?yàn)楣铝Ⅻc(diǎn)的骨架就是它自身??偨Y(jié)一下,有如下的判
24、據(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)的情況查表,假設(shè)表中的元素是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ù)去查表即可。例如上面的例子中 對(duì)
25、應(yīng)表中的第0項(xiàng),該項(xiàng)應(yīng)該為0;對(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;對(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,
26、0,0,0,0,0,;有了這張表,算法就很簡單了,每次對(duì)一行一行的將整個(gè)圖象掃描一遍,對(duì)于每個(gè)點(diǎn)不包括邊界點(diǎn),計(jì)算它在表中對(duì)應(yīng)的索引,假設(shè)為0,那么保存,否那么刪除該點(diǎn)。如果這次掃描沒有一個(gè)點(diǎn)被刪除, 那么循環(huán)結(jié)束,剩下的點(diǎn)就是骨架點(diǎn), 如果有點(diǎn)被刪除,那么進(jìn)行新的一輪掃描,如此反復(fù),直到?jīng)]有點(diǎn)被刪除為止。實(shí)際上,該算法有一些缺陷。舉個(gè)簡單的例子,有一個(gè)黑色矩形,如圖6.23所示。圖6.23經(jīng)過細(xì)化后,我們預(yù)期的結(jié)果是一條水平直線,且位于該黑色矩形的中心。實(shí)際的結(jié)果確實(shí)是一條水平直線,但不是位于黑色矩形的中心,而是最下面的一條邊。為什么會(huì)這樣,我們來分析一下:在從上到下,從左到右的掃描過程中,
27、我們遇到的第一個(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é)果。解決的方法是,在每一行水平掃描的過程中,先判斷每一點(diǎn)的左右鄰居,如果都是黑點(diǎn),那么該點(diǎn)不做處理。另外, 如果某個(gè)黑點(diǎn)被刪除了,那么跳過它的右鄰居,處理下一個(gè)點(diǎn)。這樣就防止了上述的問
28、題。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,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,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
29、0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,1,0,0,1,0,0,0圖6.23黑色矩形圖6.24圖6.23細(xì)化后的結(jié)果解決了上面的問題, 我們來看看處理后的結(jié)果,如圖6.24所示。這次變成一小段豎線了, 還是不對(duì),是不是很沮喪?別著急,讓我們再來分析一下:在上面的算法中,我們遇到的第一個(gè)能刪除的點(diǎn)就是黑色矩形的左上角點(diǎn);第二個(gè) 是第一行的最右邊的點(diǎn),即黑色矩形的右上角點(diǎn);第三個(gè)是第二行的最左邊的點(diǎn);第四個(gè)是第二行的最右邊的 點(diǎn);整個(gè)圖象處理這樣一次后,寬度減少2。每次都是如此,直到剩最中間一列,就不能再刪了。為什么會(huì)這 樣呢?原因是這樣的處理過程只實(shí)現(xiàn)了水
30、平細(xì)化,如果在每一次水平細(xì)化后,再進(jìn)行一次垂直方向的細(xì)化只要把上述過程的行列換一下,就可以了。這樣一來,每處理一次,刪除點(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 Thin
31、ning(HWND hWnd)(OffBits,BufSize;LPBITMAPINFOHEADER lpImgData;LPSTRlpPtr;HLOCALhTempImgData;LPBITMAPINFOHEADER lpTempImgData;LPSTRlpTempPtr;HDChDc;HFILEhf;LONGx,y;intnum;BOOLFinished;intnw,n,ne,w,e,sw,s,se;為了處理的方便,仍采用256級(jí)灰度圖,不過只用調(diào)色板中0和255兩項(xiàng)if( NumColors!=256)(MessageBox(hWnd,Must be a mono bitmap wit
32、h grayscale palette!,DWORDError 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_ICONEXC
33、LAMATION);return FALSE;lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);拷貝頭信息和位圖數(shù)據(jù)memcpy(lpTempImgData,lpImgData,BufSize);結(jié)束標(biāo)志置成假Finished=FALSE;while(!Finished)( /還沒有結(jié)束/結(jié)束標(biāo)志置成假Finished=TRUE;先進(jìn)行水平方向的細(xì)化for (y=1;ybi.biHeight-1;y+) /注意為防止越界,y的范
34、圍從1到高度-2/IpPtr指向原圖數(shù)據(jù),lpTempPtr指向新圖數(shù)據(jù)lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes);x=1;注意為防止越界,x的范圍從1到寬度-2while(xbi.biWidth-1)if(*(lpPtr+x)=0) /是黑點(diǎn)才做處理w=(unsigned char)*(lpPtr+x-1);左鄰點(diǎn)e=(unsigned char)*(lpPtr+x+1);右鄰點(diǎn)if(if( (w=
35、255)|(w=255)| (e=255)(e=255)(如果左右兩個(gè)鄰居中至少有一個(gè)是白點(diǎn)才處理nw=(unsigned char)*(lpPtr+x+LineBytes-1); /左上鄰點(diǎn)n=(unsigned char)*(lpPtr+x+LineBytes); /上鄰點(diǎn)ne=(unsigned char)*(lpPtr+x+LineBytes+1); /右上鄰點(diǎn)sw=(unsigned char)*(lpPtr+x-LineBytes-1); /左下鄰點(diǎn)s=(unsigned char)*(lpPtr+x-LineBytes); /下鄰點(diǎn)se=(unsigned char)*(lpPt
36、r+x-LineBytes+1); /右下鄰點(diǎn)/計(jì)算索引num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128;if(erasetablenum=1) /經(jīng)查表,可以刪除/在原圖緩沖區(qū)中將該黑點(diǎn)刪除*(lpPtr+x)=(BYTE)255;結(jié)果圖中該黑點(diǎn)也刪除*(lpTempPtr+x)=(BYTE)255;Finished=FALSE;Finished=FALSE; /有改動(dòng),結(jié)束標(biāo)志置成假x+;x+; /水平方向跳過一個(gè)象素x+; /掃描下一個(gè)象素再進(jìn)行垂直方向的細(xì)化for (x=1;xbi.bi
37、Width-1;x+)( /注意為防止越界,x的范圍從1到寬度-2y=1; /注意為防止越界,y的范圍從1到高度-2while(ybi.biHeight-1)lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);lpTempPtr=(char*)lpTempImgData+(BufSize-LineBytes-y*LineBytes);if(*(lpPtr+x)=0) /是黑點(diǎn)才做處理n=(unsigned char)*(lpPtr+x+LineBytes);s=(unsigned char)*(lpPtr+x-LineBytes);if(if( (n=255)|(n=255)| (s=255)(s=255)(如果上下兩個(gè)鄰居中至少有一個(gè)是白點(diǎn)才處理nw=(unsigned char)*(lpPtr+x+LineBytes-1);ne=(unsigned char)*(lpPtr+x+LineBytes+1);w=(unsigned char)*(lpPtr+x-1);e=(unsigned char)*(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 【正版授權(quán)】 IEC 63584:2024 EN Open Charge Point Protocol (OCPP)
- 公司裝修合同正規(guī)
- 浴場承包合同
- 電腦維護(hù)保養(yǎng)合同
- 公立醫(yī)院職工購房借款合同
- 化糞池設(shè)備銷售合同
- 房地產(chǎn)物業(yè)售樓處服務(wù)合同
- 場地房屋租賃服務(wù)合同
- 擔(dān)保借款三方合同
- 擋土墻施工承包合同
- 電力電子技術(shù)全套課件
- 配電箱(剩余電流動(dòng)作斷路器)檢測報(bào)告
- DB32T 4004-2021 水質(zhì) 17種全氟化合物的測定 高效液相色譜串聯(lián)質(zhì)譜法
- JIS C9335-2-5-2021 家用和類似用途電器.安全性.第2-5部分:洗碗機(jī)的特殊要求
- 建設(shè)年飼養(yǎng)240萬只蛋雛雞培育基地項(xiàng)目可行性研究報(bào)告
- 大連理工畫法幾何電子教案2003第八章
- 中國數(shù)學(xué)發(fā)展歷史(課堂PPT)
- 一至六年級(jí)下冊音樂期末試卷及答案
- 黃金太陽漆黑的黎明金手指
- 節(jié)水灌溉理論與技術(shù)
- 工商企業(yè)管理專業(yè)專科畢業(yè)論文
評(píng)論
0/150
提交評(píng)論