本篇文章要分享的是基於MATLAB的腐蝕膨脹算法實現,腐蝕膨脹是形態學圖像處理的基礎,腐蝕在二值圖像的基礎上作「收縮」或「細化」操做,膨脹在二值圖像的基礎上作「加長」或「變粗」的操做。html
什麼是二值圖像呢?把一幅圖片看作成一個二維的數組,那麼二值圖像是一個只有0和1的邏輯數組,咱們前面Sobel邊緣檢測後的圖像輸出邊緣效果,設置個閾值,大於閾值輸出爲1,小於閾值輸出爲0,最後輸出就是一幅二維圖像了。算法
腐蝕是一種消除邊界點,使邊界向內部收縮的過程。能夠用來消除小且無心義的物體。用3X3的結構元素,掃描圖像的每個像素,用結構元素與其覆蓋的二值圖像作「與」操做,若是都爲1,結果圖像的該像素爲1。不然爲0。結果會使二值圖像小一圈。數組
有一個形象的比喻來能夠說明該運算,用0表示蛀蟲,1表示大米。蛀蟲腐蝕大米的過程即是腐蝕運算,微信
腐蝕函數
如圖所示,對於一個像素矩陣而言,只要有蛀蟲(0)的存在,大米(1)就會被腐蝕掉了,即便只存在一個蛀蟲(0),可是仍是會被蛀蟲腐蝕完畢,最後一幅圖上面因爲沒有蛀蟲(0)因此大米完整無缺。spa
關於算法的實現,能夠用下式子來表示,即3x3像素的運算:code
P = P11 & P12 & P13 & P21 & P22 & P23 & P31 & P32 & P33htm
在FPGA中,爲了經過面積去換速度,咱們將上式改變以下: blog
P1 = P11 & P12 & P13圖片
P2 = P21 & P22 & P23
P3 = P31 & P32 & P33
P = P1 & P2 & P3
MATLAB中能夠直接寫一個按位或運算。
膨脹是將與物體接觸的全部背景點合併到該物體中,使邊界向外部擴張的過程。能夠用來填補物體中的空洞。用3X3的結構元素,掃描圖像的每個像素,用結構元素與其覆蓋的二值圖像作「與」操做,若是都爲0,結果圖像的該像素爲0,。不然爲1。結果使二值圖像擴大一圈。
先腐蝕後膨脹的過程稱爲開運算。用來消除小物體、在纖細點處分離物體、平滑較大物體的邊界的同時並不明顯的改變其面積。先膨脹後腐蝕的過程稱爲比運算,用來填充物體內細小空間、鏈接鄰近物體、平滑其邊界的同時並不明顯改變其面積。
膨脹算法用最簡單的比喻來描述:0表示害蟲,1表示青蛙,青蛙吃了害蟲表示膨脹運算,咱們用3*3像素陣列來解釋:
膨脹
如圖所示,圖左只有害蟲(0),因此害蟲都活着,中間那個圖,雖然只有一個害蟲,可是仍是會被青蛙所有吃掉,最右邊的那幅圖,都是青蛙,因此青蛙始終是青蛙。
關於算法的實現,能夠用下式子來表示,即3x3像素的運算:
P = P11 | P12 | P13 | P21 | P22 | P23 | P31 | P32 | P33
在HDL中,爲了經過面積去換速度,咱們將上式改變以下:
P1 = P11 | P12 | P13
P2 = P21 | P22 | P23
P3 = P31 | P32 | P33
P = P1 | P2 | P3
MATLAB中能夠直接寫一個按位與運算。
先腐蝕後膨脹叫開運算,開運算的做用是清除圖像邊緣周圍非邊緣的細小的點。先膨脹後腐蝕爲閉運算,閉運算的做用是清除圖像內部的空洞,
若是咱們的目標物體外面有不少無關的小區域,就用開運算去除掉;若是物體內部有不少小黑洞,就用閉運算填充掉。
bitand(), 對十進制數進行逐位邏輯與運算:先將十進制數轉換成二進制數,而後逐位與運算,其運算結果轉換爲十進制。
bitor(), 對十進制數進行逐位邏輯或運算:先將十進制數轉換成二進制數,而後逐位與運算,其運算結果轉換爲十進制。
1 %RGB_YCbCr 2 clc; 3 clear all; 4 close all; 5 6 RGB_data = imread('lena.jpg'); 7 8 R_data = RGB_data(:,:,1); 9 G_data = RGB_data(:,:,2); 10 B_data = RGB_data(:,:,3); 11 12 %imshow(RGB_data); 13 14 [ROW,COL, DIM] = size(RGB_data); 15 16 Y_data = zeros(ROW,COL); 17 Cb_data = zeros(ROW,COL); 18 Cr_data = zeros(ROW,COL); 19 Gray_data = RGB_data; 20 21 for r = 1:ROW 22 for c = 1:COL 23 Y_data(r, c) = 0.299*R_data(r, c) + 0.587*G_data(r, c) + 0.114*B_data(r, c); 24 Cb_data(r, c) = -0.172*R_data(r, c) - 0.339*G_data(r, c) + 0.511*B_data(r, c) + 128; 25 Cr_data(r, c) = 0.511*R_data(r, c) - 0.428*G_data(r, c) - 0.083*B_data(r, c) + 128; 26 end 27 end 28 29 Gray_data(:,:,1)=Y_data; 30 Gray_data(:,:,2)=Y_data; 31 Gray_data(:,:,3)=Y_data; 32 33 figure; 34 imshow(Gray_data); 35 36 %Median Filter 37 imgn = imnoise(Gray_data,'salt & pepper',0.02); 38 39 figure; 40 imshow(imgn); 41 42 Median_Img = Gray_data; 43 for r = 2:ROW-1 44 for c = 2:COL-1 45 median3x3 =[imgn(r-1,c-1) imgn(r-1,c) imgn(r-1,c+1) 46 imgn(r,c-1) imgn(r,c) imgn(r,c+1) 47 imgn(r+1,c-1) imgn(r+1,c) imgn(r+1,c+1)]; 48 sort1 = sort(median3x3, 2, 'descend'); 49 sort2 = sort([sort1(1), sort1(4), sort1(7)], 'descend'); 50 sort3 = sort([sort1(2), sort1(5), sort1(8)], 'descend'); 51 sort4 = sort([sort1(3), sort1(6), sort1(9)], 'descend'); 52 mid_num = sort([sort2(3), sort3(2), sort4(1)], 'descend'); 53 Median_Img(r,c) = mid_num(2); 54 end 55 end 56 57 figure; 58 imshow(Median_Img); 59 60 %Sobel_Edge_Detect 61 62 Median_Img = double(Median_Img); 63 Sobel_Threshold = 150; 64 Sobel_Img = zeros(ROW,COL); 65 66 for r = 2:ROW-1 67 for c = 2:COL-1 68 Sobel_x = Median_Img(r-1,c+1) + 2*Median_Img(r,c+1) + Median_Img(r+1,c+1) - Median_Img(r-1,c-1) - 2*Median_Img(r,c-1) - Median_Img(r+1,c-1); 69 Sobel_y = Median_Img(r-1,c-1) + 2*Median_Img(r-1,c) + Median_Img(r-1,c+1) - Median_Img(r+1,c-1) - 2*Median_Img(r+1,c) - Median_Img(r+1,c+1); 70 Sobel_Num = abs(Sobel_x) + abs(Sobel_y); 71 %Sobel_Num = sqrt(Sobel_x^2 + Sobel_y^2); 72 if(Sobel_Num > Sobel_Threshold) 73 Sobel_Img(r,c)=255; 74 else 75 Sobel_Img(r,c)=0; 76 end 77 end 78 end 79 80 figure; 81 imshow(Sobel_Img); 82 83 %imopen Erosion_Dilation 84 %Erosion 85 % Erosion_img = zeros(ROW,COL); 86 % for r = 2:ROW-1 87 % for c = 2:COL-1 88 % and1 = bitand(Sobel_Img(r-1, c-1), bitand(Sobel_Img(r-1, c), Sobel_Img(r-1, c+1))); 89 % and2 = bitand(Sobel_Img(r, c-1), bitand(Sobel_Img(r, c), Sobel_Img(r, c+1))); 90 % and3 = bitand(Sobel_Img(r+1, c-1), bitand(Sobel_Img(r+1, c), Sobel_Img(r+1, c+1))); 91 % Erosion_img(r, c) = bitand(and1, bitand(and2, and3)); 92 % end 93 % end 94 95 % figure; 96 % imshow(Erosion_img); 97 98 % %Dilation 99 % Dilation_img = zeros(ROW,COL); 100 % for r = 2:ROW-1 101 % for c = 2:COL-1 102 % or1 = bitor(Erosion_img(r-1, c-1), bitor(Erosion_img(r-1, c), Erosion_img(r-1, c+1))); 103 % or2 = bitor(Erosion_img(r, c-1), bitor(Erosion_img(r, c), Erosion_img(r, c+1))); 104 % or3 = bitor(Erosion_img(r+1, c-1), bitor(Erosion_img(r+1, c), Erosion_img(r+1, c+1))); 105 % Dilation_img(r, c) = bitor(or1, bitor(or2, or3)); 106 % end 107 % end 108 109 % figure; 110 % imshow(Dilation_img); 111 112 %imclose Erosion_Dilation 113 %Dilation 114 Dilation_img = zeros(ROW,COL); 115 for r = 2:ROW-1 116 for c = 2:COL-1 117 or1 = bitor(Sobel_Img(r-1, c-1), bitor(Sobel_Img(r-1, c), Sobel_Img(r-1, c+1))); 118 or2 = bitor(Sobel_Img(r, c-1), bitor(Sobel_Img(r, c), Sobel_Img(r, c+1))); 119 or3 = bitor(Sobel_Img(r+1, c-1), bitor(Sobel_Img(r+1, c), Sobel_Img(r+1, c+1))); 120 Dilation_img(r, c) = bitor(or1, bitor(or2, or3)); 121 end 122 end 123 124 figure; 125 imshow(Dilation_img); 126 127 %Erosion 128 Erosion_img = zeros(ROW,COL); 129 for r = 2:ROW-1 130 for c = 2:COL-1 131 and1 = bitand(Dilation_img(r-1, c-1), bitand(Dilation_img(r-1, c), Dilation_img(r-1, c+1))); 132 and2 = bitand(Dilation_img(r, c-1), bitand(Dilation_img(r, c), Dilation_img(r, c+1))); 133 and3 = bitand(Dilation_img(r+1, c-1), bitand(Dilation_img(r+1, c), Dilation_img(r+1, c+1))); 134 Erosion_img(r, c) = bitand(and1, bitand(and2, and3)); 135 end 136 end 137 138 figure; 139 imshow(Erosion_img);
爲了能夠清晰的看到圖像邊緣的變化,咱們把黑色做爲背景,白色做爲邊緣。
Sobel邊緣檢測後的lena
腐蝕後的lena
膨脹後的lena
先腐蝕後膨脹開運算lena
先膨脹後腐蝕閉運算lena
從上面兩幅圖能夠看出,腐蝕後的圖像邊緣明顯變細,消除了更多假邊緣,在腐蝕基礎上使用膨脹算法的lena將腐蝕後的邊緣擴大、加粗,這樣看起來更清楚。
轉載請註明出處:NingHeChuan(寧河川)
我的微信訂閱號:開源FPGA
若是你想及時收到我的撰寫的博文推送,能夠掃描左邊二維碼(或者長按識別二維碼)關注我的微信訂閱號
知乎ID:NingHeChuan
微博ID:NingHeChuan