Basic Morphological Operations
Morphological operation (형태학적 연산) 은 structuring elements (구조 요소) 라는 것을
원본 이미지 - 주로 흑백인 BW 또는 gray scale 이미지 - 에 적용하여 대상 픽셀과 그 주변의
픽셀들에 연산을 수행하는것을 의미 합니다.
여기서 structuring elements (구조 요소)는 앞서 소개한 선형 공간 필터링 (linear spatial filtering)
에 나오는 kernel 으로써 이해할 수 있습니다. 즉, 이미지의 필터링 과정과 같이 사용자가
원하는/지정한 모양의 kernel 또는 구조 요소를 반복적으로 이동하며 입력 이미지에 적용하여
연산을 수행후 사용자가 요구하는 결과 이미지를 얻을때까지 반복적으로 입력 이미지와 비교를
하는 과정과 동일 합니다. ( [MATLAB 영상처리 기초 6] 선형 공간 필터링 참조 )
기본적인 형태학적 연산으로는 dilation과 erosion이 있습니다. Dilation은 - BW 또는 gray scale
이미지에서 - 이미지상의 object 가장자리(혹은 윤곽선, boundary) 에 픽셀을 확장시키는 반면,
erosion은 반대로 픽셀을 없애는 일을 합니다.
그리고 이 두가지 연산의 순서, 반복횟수, structuring elements의 모양/크기 등을 조합하여
다양한 작업을 수행할 수 있습니다. 예를들어, 노이즈 제거, 이미지의 object 검출, 크기/중심점
계산, 윤곽선 그리기, 배경과 대상 이미지 분리 등에 자주 이용됩니다.
Dilation, Erosion, and Structuring Elements
Dilation은 이미지상의 object의 윤곽을 더 뚜렷하게 하며, 구멍을 채우고, 얇은선을 두껍게
만드는 등 object를 크고 두껍게 하는 경향을 갖습니다. 이 연산은 structuring elements의
모양과 크기에 따라 결과가 달라집니다.
다음은 3-by-3 크기의 정사각형 structuring element를 7-by-8의 BW 데이터에 적용하여
연산하는 예시를 보입니다. 배경이 되는 7-by-8의 BW 데이터의 가운데 부분만 픽셀값 '1'이
분포하고, 3-by-3 structuring element의 가운데 빨간색 네모는 연산이 수행될 대상 픽셀
입니다. 밑의 좌측에서 보듯이 structuring element가 위치한 구역에 대상 이미지와 하나의
픽셀이라도 '1'이 겹친다면, 빨간색 네모로 표시한 대상 픽셀은 '1' 로 변환됩니다.
만일, 대상 이미지가 gray scale 이라면, structuring element가 위치한 구역의 픽셀값 중
최대값이 대상 픽셀 (= 빨간색 네모로 표시된 픽셀) 에 지정 됩니다.
위의 structuring element를 마치 sliding window 처럼 계속 이동하면서 연산을 반복하면
다음과 같은 연산결과를 얻으며, 결과에서 보듯 대상 object의 크기가 커졌음을 알 수 있습니다.
Dilation 그리고 erosion 연산에서 structuring elements의 종류와 크기에 따라 결과가
크게 달라질 수 있습니다. MATLAB에서 기본 제공하는 structuring elements는 종류가
다양하며, 이를 생성하는 strel( ) 함수는 여러가지 입력 파라메터를 갖으므로 MATLAB의
help 메뉴에서 strel( )의 기능과 활용예를 반드시 참조하시기 바랍니다.
% make a target object on a background image
background = zeros(7,8);
background(3:4,4:5) = 1;
background(5,5) = 1;
background(4,6) = 1;
% make a structuring elements
se_square3 = strel('square',3);
% dilation
imgD_sq3 = imdilate(background,se_square3);
이번에는 동전 이미지에 각각 지름이 5, 100 픽셀인 disk 모양의 structuring elements를
적용하는 dilation 연산을 수행하겠습니다. 밑의 그림에서 A: 밝은 바탕에 동전이 놓여
있고, B: 입력 이미지를 대상으로 Otsu thresholding한 후 BW이미지를 inverse 하였습니다.
B의 이미지를 대상으로 지름 5픽셀인 disk 모양의 structuring element를 적용한 dilation
결과가 C, 지름 100픽셀의 disk의 dilation 결과는 D에 보여지고 있습니다.
B에서 보듯이 동전들에는 군데군데 빈곳이 존재하지만, C에서는 비어있는 픽셀의 대부분이
'1'로써 채워졌음을 볼 수 있습니다. 또한 포개어지거나 인접한 동전들간의 접점이 늘었음을
또한 알수 있습니다. 그리고 D에서는 동전들이 하나의 커다란 덩어리로 표현됨과 동시에 -
C에서는 보이지 않을 정도의 아주 적은수의 픽셀 모임 - 배경의 노이즈가 크게 확장되어
보입니다.
img = imread('coin.jpg');
img_gray = im2double(rgb2gray(img));
img_BW = ~imbinarize(img_gray);
% make some structuring elements
se_disk5 = strel('disk',5);
se_disk100 = strel('disk',100);
% image dilation with disk SE but different size
imgD_disk5 = imdilate(img_BW,se_disk5);
imgD_disk100 = imdilate(img_BW,se_disk100);
figure; montage({img,img_BW,imgD_disk5,imgD_disk100});
Erosion은 dilation과 달리 이미지상의 object의 윤곽을 희미하게 하며, 적은수의 픽셀
그룹을 제거하고, 선을 얇게 만드는 등 object를 작고 얇게 하는 경향을 갖습니다.
이 연산 또한 structuring elements의 모양과 크기에 따라 결과가 달라집니다.
위의 dilation에서와 달리, structuring element가 위치한 구역에 대상 이미지와 하나의
픽셀이라도 '0'이 겹친다면, 빨간색 네모로 표시한 대상 픽셀은 '0' 으로 변환됩니다.
만일, 대상 이미지가 gray scale 이라면, structuring element가 위치한 구역의 픽셀값 중
최소값이 대상 픽셀 (= 빨간색 네모로 표시된 픽셀) 에 지정 됩니다.
마찬가지로 위의 structuring element를 계속 이동하면서 연산을 반복하면 다음과
같은 연산결과를 얻으며, 결과에서 보듯 대상 object가 제거 되었음을 알 수 있습니다.
위의 dilation과 같은 연산과정으로써 동전 이미지에 각각 지름이 5, 100 픽셀인 disk 모양의
structuring elements를 적용하여 erosion 연산을 하겠습니다.
밑의 그림에서 A: 동전이 대상 object인 입력 이미지, B: 입력 이미지의 thresholding, 그리고
thresholding 된 BW이미지를 대상으로 structuring element를 적용한 erosion 연산결과가 각각
C와 D에 보여지고 있습니다.
C에서 보듯이 동전들의 군데군데 빈곳은 더 커졌으며, 포개어지거나 인접한 동전들간의
경계가 뚜렸해 졌음을 알수 있습니다. 그리고 D 에서는 크기가 커진 structuring element로
인해 object 대부분이 제거되어 표시되었습니다.
위의 dilation 결과에서 보이던 배경의 노이즈 또한 제거되었습니다.
img = imread('coin.jpg'); % imread('coin_spread.jpg');
img_gray = im2double(rgb2gray(img));
img_BW = ~imbinarize(img_gray);
% make some structuring elements
se_disk5 = strel('disk',5);
se_disk100 = strel('disk',100);
% image erosion with disk SE but different size
imgE_disk5 = imerode(img_BW,se_disk5);
imgE_disk100 = imerode(img_BW,se_disk100);
figure; montage({img,img_BW,imgE_disk5,imgE_disk100});
Morphological Opening and Closing
본 글의 서두에서 언급한 것과 같이 dilation과 erosion 이 두가지 연산의 순서, 반복횟수,
structuring elements의 모양/크기 등을 조합하여 다양한 작업을 수행할 수 있습니다.
여기에서는 dilation과 erosion 중 연산의 순서에 따른 결과를 비교해 보고자 합니다.
Morphological opening (형태학적 열기) 는 structuring elements에 의해 대상 이미지를
erosion 하고 난후, 이에 대해 같은 structuring elements를 적용해 dilation을 수행합니다.
이를 통해, 대상 이미지에서 크기가 큰 objects를 보존한 상태로 (structuring elements를
포함할 수 없을만큼) 크기가 작고 얇은선을 가진 objects 또는/그리고 노이즈를 제거하는
효과를 갖습니다.
반면에 morphological closing (형태학적 닫기) 는 대상 이미지를 dilation 하고 난후,
erosion을 수행합니다. 이로인해 대상 이미지에서 크기가 큰 objects와 구멍은 보존한 상태로
objects간의 접점을 늘려주고 길고 작은틈을 채우며 (structuring elements 보다) 작은 구멍을
채우는 효과를 보입니다.
형태학적 열기와 닫기 모두 objects 윤곽선을 부드럽게 하는 경향이 있습니다.
형태학적 열기와 닫기의 연산결과는 밑에 나타냈습니다. 입력 이미지와 그의 BW이미지(Otsu
threshodling 후 픽셀들을 inverse 하였음)는 A와 B에 보이고, 지름이 10 픽셀인 disk 모양의
structuring element를 이용한 opening과 closing의 결과는 각각 C와 D에 보였습니다.
Morphological opening의 결과로써 동전들의 대체적인 윤곽선(= boundary)은 보존되었지만
좌측 동전들의 윤곽선 일부는 제거되었고, 동전내부의 픽셀들 또한 제거되었음을 볼 수
있습니다. 한편 morphological closing의 결과인 D에서 보듯이 동전내부의 많은 부분들이 '1'
로써 채워졌고 이웃하는 동전들간의 접점이 크게 늘어났음을 알 수 있습니다.
만일 형태학적 열기 연산을 반복한다면 동전 내외부의 픽셀들은 더 많이 제거될 것이고,
형태학적 닫기 연산을 반복한다면 동전 내부의 구멍들은 모두 채워질 것입니다.
img = imread('coin.jpg'); % imread('coin_spread.jpg');
img_gray = im2double(rgb2gray(img));
img_BW = ~imbinarize(img_gray);
% make a structuring elements
se_disk10 = strel('disk',10);
% morphological opening & closing
imgO_disk10 = imopen(img_BW,se_disk10);
imgC_disk10 = imclose(img_BW,se_disk10);
figure; montage({img,img_BW,imgO_disk10,imgC_disk10});
마지막으로 본 글에 쓰인 모든 MATLAB 코드는 밑에 표시해 두었습니다.
%% dilation, erosion, and structuring elements - simple example
% make a target object on a background image
background = zeros(7,8);
background(3:4,4:5) = 1;
background(5,5) = 1;
background(4,6) = 1;
% make a structuring elements
se_square3 = strel('square',3);
% dilation
imgD_sq3 = imdilate(background,se_square3);
% ersion
imgE_sq3 = imerode(background,se_square3);
%% dilation, erosion, and structuring elements - coin example
img = imread('coin.jpg'); % imread('coin_spread.jpg');
img_gray = im2double(rgb2gray(img));
img_BW = ~imbinarize(img_gray);
% make some structuring elements
se_disk5 = strel('disk',5);
se_disk10 = strel('disk',10);
se_disk100 = strel('disk',100);
% image dilation with disk SE but different size
imgD_disk5 = imdilate(img_BW,se_disk5);
imgD_disk100 = imdilate(img_BW,se_disk100);
figure; montage({img,img_BW,imgD_disk5,imgD_disk100});
% image erosion with disk SE but different size
imgE_disk5 = imerode(img_BW,se_disk5);
imgE_disk100 = imerode(img_BW,se_disk100);
figure; montage({img,img_BW,imgE_disk5,imgE_disk100});
%% morphological opening & closing
% morphological opening & closing
imgO_disk10 = imopen(img_BW,se_disk10);
imgC_disk10 = imclose(img_BW,se_disk10);
figure; montage({img,img_BW,imgO_disk10,imgC_disk10});
출처1: 본 블로그의 작성자 직접 촬영. 학술/상업적 자유롭게 사용 가능.
https://drive.google.com/file/d/1xr5JriR4D5wWqpnD2nlzpK0z7UQySkLK/view?usp=sharing