【轉載】:Matlab 圖像處理 形態學 腐蝕 膨脹 開閉運算 連通分量
形態學是提取圖像特征的有力工具,針對二值圖像和灰度圖像的腐蝕、膨脹和重構的基本操作可以組合使用,以執行非常寬泛的任務。其練習代碼和結果如下:
1 %% 第9章 形態學處理 2 3 %% imdilate膨脹 4 clc 5 clear 6 7 A1=imread('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif'); 8 info=imfinfo('.\images\dipum_images_ch09\Fig0906(a)(broken-text).tif') 9 B=[0 1 0 10 1 1 1 11 0 1 0]; 12 A2=imdilate(A1,B);%圖像A1被結構元素B膨脹 13 A3=imdilate(A2,B); 14 A4=imdilate(A3,B); 15 16 subplot(221),imshow(A1); 17 title('imdilate膨脹原始圖像'); 18 19 subplot(222),imshow(A2); 20 title('使用B后1次膨脹后的圖像'); 21 22 subplot(223),imshow(A3); 23 title('使用B后2次膨脹后的圖像'); 24 25 subplot(224),imshow(A4); 26 title('使用B后3次膨脹后的圖像'); 27%imdilate圖像膨脹處理過程運行結果如下:

28 29 %% imerode腐蝕 30 clc 31 clear 32 A1=imread('.\images\dipum_images_ch09\Fig0908(a)(wirebond-mask).tif'); 33 subplot(221),imshow(A1); 34 title('腐蝕原始圖像'); 35 36 %strel函數的功能是運用各種形狀和大小構造結構元素 37 se1=strel('disk',5);%這里是創建一個半徑為5的平坦型圓盤結構元素 38 A2=imerode(A1,se1); 39 subplot(222),imshow(A2); 40 title('使用結構原始disk(5)腐蝕后的圖像'); 41 42 se2=strel('disk',10); 43 A3=imerode(A1,se2); 44 subplot(223),imshow(A3); 45 title('使用結構原始disk(10)腐蝕后的圖像'); 46 47 se3=strel('disk',20); 48 A4=imerode(A1,se3); 49 subplot(224),imshow(A4); 50 title('使用結構原始disk(20)腐蝕后的圖像'); 51 %圖像腐蝕處理過程運行結果如下: 52
53 %% 開運算和閉運算 54 clc 55 clear 56 f=imread('.\images\dipum_images_ch09\Fig0910(a)(shapes).tif'); 57 %se=strel('square',5');%方型結構元素 58 se=strel('disk',5');%圓盤型結構元素 59 imshow(f);%原圖像 60 title('開閉運算原始圖像') 61%運行結果如下:

62 63 %開運算數學上是先腐蝕后膨脹的結果 64 %開運算的物理結果為完全刪除了不能包含結構元素的對象區域,平滑 65 %了對象的輪廓,斷開了狹窄的連接,去掉了細小的突出部分 66 fo=imopen(f,se);%直接開運算 67 figure,subplot(221),imshow(fo); 68 title('直接開運算'); 69 70 %閉運算在數學上是先膨脹再腐蝕的結果 71 %閉運算的物理結果也是會平滑對象的輪廓,但是與開運算不同的是,閉運算 72 %一般會將狹窄的缺口連接起來形成細長的彎口,並填充比結構元素小的洞 73 fc=imclose(f,se);%直接閉運算 74 subplot(222),imshow(fc); 75 title('直接閉運算'); 76 77 foc=imclose(fo,se);%先開后閉運算 78 subplot(223),imshow(foc); 79 title('先開后閉運算'); 80 81 fco=imopen(fc,se);%先閉后開運算 82 subplot(224),imshow(fco); 83 title('先閉后開運算'); 84%開閉運算結果如下:

85 86 %先膨脹再腐蝕 87 fse=imdilate(f,se);%膨脹 88 89 %gcf為得到當前圖像的句柄,當前圖像是指例如PLOT,TITLE,SURF等 90 %get函數為得到物體的屬性,get(0,'screensize')為返回所有物體screensize屬性值 91 %set函數為設置物體的屬性 92 figure,set(gcf,'outerposition',get(0,'screensize'));%具體目的是設置當前窗口的大小 93 subplot(211),imshow(fse); 94 title('使用disk(5)先膨脹后的圖像'); 95 96 fes=imerode(fse,se); 97 subplot(212),imshow(fes); 98 title('使用disk(5)先膨脹再腐蝕后的圖像'); 99%先膨脹后腐蝕圖像如下:

100 101 %先腐蝕再膨脹 102 fse=imerode(f,se); 103 figure,set(gcf,'outerposition',get(0,'screensize')) 104 subplot(211),imshow(fse); 105 title('使用disk(5)先腐蝕后的圖像'); 106 107 fes=imdilate(fse,se); 108 subplot(212),imshow(fes); 109 title('使用disk(5)先腐蝕再膨脹后的圖像'); 110%先腐蝕后膨脹的圖像如下:

111 112 %% imopen imclose在指紋上的應用 113 clc 114 clear 115 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif'); 116 se=strel('square',3);%邊長為3的方形結構元素 117 subplot(121),imshow(f); 118 title('指紋原始圖像'); 119 120 A=imerode(f,se);%腐蝕 121 subplot(122),imshow(A); 122 title('腐蝕后的指紋原始圖像'); 123%指紋原始圖像和腐蝕后的圖像結果如下:

124 125 fo=imopen(f,se); 126 figure,subplot(221),imshow(fo); 127 title('使用square(3)開操作后的圖像'); 128 129 fc=imclose(f,se); 130 subplot(222),imshow(fc); 131 title('使用square閉操作后的圖像'); 132 133 foc=imclose(fo,se); 134 subplot(223),imshow(foc); 135 title('使用square(3)先開后閉操作后的圖像') 136 137 fco=imopen(fc,se); 138 subplot(224),imshow(fco); 139 title('使用square(3)先閉后開操作后的圖像'); 140%指紋圖像開閉操作過程結果如下:

141 142 %% bwhitmiss擊中或擊不中變換 143 clc 144 clear 145 f=imread('.\images\dipum_images_ch09\Fig0913(a)(small-squares).tif'); 146 imshow(f); 147 title('擊中或不擊中原始圖像'); 148%擊中或不擊中原始圖像顯示結果如下:

149 150 B1=strel([0 0 0;0 1 1;0 1 0]);%擊中:要求擊中所有1的位置 151 B2=strel([1 1 1;1 0 0;1 0 0]);%擊不中,要求擊不中所有1的位置 152 B3=strel([0 1 0;1 1 1;0 1 0]);%擊中 153 B4=strel([1 0 1;0 0 0;0 0 0]);%擊不中 154 B5=strel([0 0 0;0 1 0;0 0 0]);%擊中 155 B6=strel([1 1 1;1 0 0;1 0 0]);%擊不中 156 157 g=imerode(f,B1)&imerode(~f,B2)%利用定義來實現擊中或擊不中 158 figure,subplot(221),imshow(g); 159 title('定義實現組1擊中擊不中圖像'); 160 161 g1=bwhitmiss(f,B1,B2); 162 subplot(222),imshow(g1); 163 title('結構數組1擊中擊不中后的圖像'); 164 165 g2=bwhitmiss(f,B3,B4); 166 subplot(223),imshow(g2); 167 title('結構數組2擊中擊不中的圖像'); 168 169 g3=bwhitmiss(f,B5,B6); 170 subplot(224),imshow(g3); 171 title('結構數組3擊中擊不中的圖像'); 172%擊中擊不中變換后圖像如下:

173 174 %%makelut 175 clc 176 clear 177 178 f=inline('sum(x(:))>=3');%inline是用來定義局部函數的 179 lut2=makelut(f,2)%為函數f構造一個接收2*2矩陣的查找表 180 lut3=makelut(f,3) 181 182 %% Conway生命游戲 183 clc 184 clear 185 lut=makelut(@conwaylaws,3); 186 bw1= [0 0 0 0 0 0 0 0 0 0 187 0 0 0 0 0 0 0 0 0 0 188 0 0 0 1 0 0 1 0 0 0 189 0 0 0 1 1 1 1 0 0 0 190 0 0 1 0 0 0 0 1 0 0 191 0 0 1 0 1 1 0 1 0 0 192 0 0 1 0 0 0 0 1 0 0 193 0 0 0 1 1 1 1 0 0 0 194 0 0 0 0 0 0 0 0 0 0 195 0 0 0 0 0 0 0 0 0 0 ]; 196 subplot(221),imshow(bw1,'InitialMagnification','fit'); 197 title('Generation 1'); 198 199 bw2=applylut(bw1,lut); 200 subplot(222),imshow(bw2,'InitialMagnification','fit'), 201 title('Generation 2'); 202 203 bw3=applylut(bw2,lut); 204 subplot(223),imshow(bw3,'InitialMagnification','fit'); 205 title('Generation 3'); 206 207 temp=bw1; 208 for i=2:100 209 bw100=applylut(temp,lut); 210 temp=bw100; 211 end 212 subplot(224),imshow(bw100,'InitialMagnification','fit') 213 title('Generation 100'); 214%顯示Generation結果如下:

215 216 %% getsequence 217 clc 218 clear 219 se=strel('diamond',5) 220 decomp=getsequence(se)%getsequence函數為得到分解的strel序列 221 decomp(1) 222 decomp(2) 223 224 %% endpoints 225 clc 226 clear 227 228 f1=imread('.\images\dipum_images_ch09\Fig0914(a)(bone-skel).tif'); 229 subplot(121),imshow(f1); 230 title('原始形態骨架圖像'); 231 232 g1=endpoints(f1); 233 %set(gcf,'outerposition',get(0,'screensize'));%運行完后自動生成最大的窗口 234 subplot(122),imshow(g1); 235 title('骨架圖像的端點圖像');236 %骨架頭像端點檢測頭像如下: 237 238 f2=imread('.\images\dipum_images_ch09\Fig0916(a)(bone).tif'); 239 figure,subplot(121),imshow(f2); 240 title('原始骨頭圖像'); 241 242 g2=endpoints(f2); 243 subplot(122),imshow(g2); 244 title('骨頭圖像端點頭像');%結果是沒有端點 245%骨頭頭像端點檢測圖像如下:

246 247 %% bwmorph組合常見形態學之細化 248 clc 249 clear 250 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif'); 251 subplot(221),imshow(f); 252 title('指紋圖像細化原圖'); 253 254 g1=bwmorph(f,'thin',1); 255 subplot(222),imshow(g1); 256 title('指紋圖像細化原圖'); 257 258 g2=bwmorph(f,'thin',2); 259 subplot(223),imshow(g2); 260 title('指紋圖像細化原圖'); 261 262 g3=bwmorph(f,'thin',Inf); 263 subplot(224),imshow(g3); 264 title('指紋圖像細化原圖'); 265%指紋圖像細化過程顯示如下:

266 267 %% bwmorph組合常見形態學之骨骼化 268 clc 269 clear 270 f=imread('.\images\dipum_images_ch09\Fig0911(a)(noisy-fingerprint).tif'); 271 subplot(131),imshow(f); 272 title('指紋圖像骨骼化原圖'); 273 274 fs=bwmorph(f,'skel',Inf); 275 subplot(132),imshow(fs); 276 title('指紋圖像骨骼化'); 277 278 for k=1:5 279 fs=fs&~endpoints(fs); 280 end 281 subplot(133),imshow(fs); 282 title('指紋圖像修剪后骨骼話'); 283%指紋圖像骨骼化過程顯示:

284 285 %% 使用函數bwlabel標注連通分量 286 clc 287 clear 288 f=imread('.\images\dipum_images_ch09\Fig0917(a)(ten-objects).tif'); 289 imshow(f),title('標注連通分量原始圖像'); 290%其結果顯示如下:

291 292 [L,n]=bwlabel(f);%L為標記矩陣,n為找到連接分量的總數 293 [r,c]=find(L==3);%返回第3個對象所有像素的行索引和列索引 294 295 rbar=mean(r); 296 cbar=mean(c); 297 298 figure,imshow(f) 299 hold on%保持當前圖像使其不被刷新 300 for k=1:n 301 [r,c]=find(L==k); 302 rbar=mean(r); 303 cbar=mean(c); 304 plot(cbar,rbar,'Marker','o','MarkerEdgeColor','k',... 305 'MarkerFaceColor','k','MarkerSize',10);%這個plot函數用法不是很熟悉 306 plot(cbar,rbar,'Marker','*','MarkerFaceColor','w');%其中的marker為標記 307 end 308 title('標記所有對象質心后的圖像');

309 310 %% 由重構做開運算 311 clc 312 clear 313 f=imread('.\images\dipum_images_ch09\Fig0922(a)(book-text).tif'); 314 subplot(321),imshow(f); 315 title('重構原始圖像'); 316 317 fe=imerode(f,ones(51,1));%豎線腐蝕 318 subplot(322),imshow(fe); 319 title('使用豎線腐蝕后的結果'); 320 321 fo=imopen(f,ones(51,1));%豎線做開運算 322 subplot(323),imshow(fo); 323 title('使用豎線做開運算結果'); 324 325 fobr=imreconstruct(fe,f);%fe做標記 326 subplot(324),imshow(fobr); 327 title('使用豎線做重構開運算'); 328 329 ff=imfill(f,'holes');%對f進行孔洞填充 330 subplot(325),imshow(ff); 331 title('對f填充孔洞后的圖像'); 332 333 fc=imclearborder(f,8);%清除邊界,2維8鄰接 334 subplot(326),imshow(fc); 335 title('對f清除邊界后的圖像'); 336%圖像重構過程顯示如下:

337 338 %% 使用頂帽變換和底帽變換 339 clc 340 clear 341 f=imread('.\images\dipum_images_ch09\Fig0926(a)(rice).tif'); 342 subplot(221),imshow(f); 343 title('頂帽底帽變換原始圖像'); 344 345 se=strel('disk',10);%產生結構元素 346 %頂帽變換是指原始圖像減去其開運算的圖像 347 %而開運算可用於補償不均勻的背景亮度,所以用一個大的結構元素做開運算后 348 %然后用原圖像減去這個開運算,就得到了背景均衡的圖像,這也叫做是圖像的頂帽運算 349 f1=imtophat(f,se);%使用頂帽變換 350 subplot(222),imshow(f1); 351 title('使用頂帽變換后的圖像'); 352 353 %底帽變換是原始圖像減去其閉運算后的圖像 354 f2=imbothat(imcomplement(f),se);%使用底帽變換,為什么原圖像要求補呢? 355 %f2=imbothat(f,se);%使用底帽變換 356 subplot(223),imshow(f2); 357 title('使用底帽變換后的圖像'); 358 359 %頂帽變換和底帽變換聯合起來用,用於增加對比度 360 f3=imsubtract(imadd(f,imtophat(f,se)),imbothat(f,se));%里面參數好像不合理? 361 subplot(224),imshow(f3); 362 title('使用頂帽底帽聯合變換后圖像'); 363%頂帽底帽變換過程圖像如下:

364 365 %%使用開運算和閉運算做形態學平滑 366 %由於開運算可以除去比結構元素更小的明亮細節,閉運算可以除去比結構元素更小的暗色細節 367 %所以它們經常組合起來一起進行平滑圖像並去除噪聲 368 clc 369 clear 370 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif'); 371 subplot(221),imshow(f); 372 title('木釘圖像原圖'); 373 374 se=strel('disk',5);%disk其實就是一個八邊形 375 fo=imopen(f,se);%經過開運算 376 subplot(222),imshow(f); 377 title('使用半徑5的disk開運算后的圖像'); 378 379 foc=imclose(fo,se); 380 subplot(223),imshow(foc); 381 title('先開后閉的圖像'); 382 383 fasf=f; 384 for i=2:5 385 se=strel('disk',i); 386 fasf=imclose(imopen(fasf,se),se); 387 end 388 subplot(224),imshow(fasf); 389 title('使用開閉交替濾波后圖像'); 390%使用開運算和閉運算做形態學平滑結果如下:

391 392 %% 顆粒分析 393 clc 394 clear 395 f=imread('.\images\dipum_images_ch09\Fig0925(a)(dowels).tif'); 396 397 sumpixels=zeros(1,36); 398 for k=0:35 399 se=strel('disk',k); 400 fo=imopen(f,se); 401 sumpixels(k+1)=sum(fo(:)); 402 end 403 404 %可以看到,連續開運算之間的表面積會減少 405 plot(0:35,sumpixels),xlabel('k'),ylabel('surface area'); 406 title('表面積和結構元素半徑之間的關系'); 407%其運算結果如下:

408 409 figure,plot(-diff(sumpixels));%diff()函數為差分或者近似倒數,即相鄰2個之間的差值 410 xlabel('k'),ylabel('surface area reduction'); 411 title('減少的表面積和結構元素半徑之間的關系'); 412%其運算結果如下:

413 414 %% 使用重構刪除復雜圖像的背景 415 clc 416 clear 417 f=imread('.\images\dipum_images_ch09\Fig0930(a)(calculator).tif'); 418 subplot(221),imshow(f); 419 title('灰度級重構原圖像'); 420 421 f_obr=imreconstruct(imerode(f,ones(1,71)),f); 422 subplot(222),imshow(f_obr); 423 title('經開運算重構圖'); 424 425 f_o=imopen(f,ones(1,71)); 426 subplot(223),imshow(f_o); 427 title('經開運算后圖'); 428 429 f_thr=imsubtract(f,f_obr); 430 subplot(224),imshow(f_thr); 431 title('頂帽運算重構圖') 432%使用重構刪除復雜圖像的背景1:

433 434 f_th=imsubtract(f,f_o) 435 figure,subplot(221),imshow(f_th); 436 title('經頂帽運算圖'); 437 438 g_obr=imreconstruct(imerode(f_thr,ones(1,11)),f_thr); 439 subplot(222),imshow(g_obr); 440 title('用水平線對f_thr經開運算后重構圖'); 441 442 g_obrd=imdilate(g_obr,ones(1,2)); 443 subplot(223),imshow(g_obrd); 444 title('使用水平線對上圖進行膨脹'); 445 446 f2=imreconstruct(min(g_obrd,f_thr),f_thr); 447 subplot(224),imshow(f2); 448 title('最后的重構結果'); 449%使用重構刪除復雜圖像的背景2:

形態學這一章很有用,因為它還可以應用在圖像分割中。

236