요약
Morphological transformation (형태변형)은 이미지의 형태를 변형하는 작업들 중 하나를 말한다. 이미지의 형태를 변형하는 하는 방법은 여러가지가 있는데, 주로 "입력 이미지"와 "구조적 원소(=커널이미지)"을 이용한 경우를 말한다. 그리고 형태변형은 주로 이진화 이미지(Binary image, 흑백이미지으로 0(흑), 1(백)으로만 이뤄져있는 이미지)를 연산하는 것을 의미한다[1]*. 주로 Erosion, Dilation이 주로 연산이며 Open, closing은 이것들의 변형들이다 .
*주로라는 것은 이진화 이미지가 아닌 경우도 쓸 수 있다(예, grayscale)
주로 아래와 같은 연산들이 대표적으로 쓰인다. 아래의 글을 봐도 잘 이해가 안되는데, 예시와 함께 보는 것을 권장한다.
- Erosion (부식, 침식, Shrink, Reduce): 이미지의 boundary(가장자리)를 부식시키는 작업. 각 오브젝트의 두께가 줄여진다. [2]
- Dilation (확장):이미지의 boundary(가장자리)를 확장시키는 작업. 각 오브젝트의 두께가 커진다.
- Opening (오프닝): Erosion후에 Dilation을 적용하는 연산. Erosion으로 노이즈 같은 점을 없애주고 이미지를 확장하기에 noise reduction용으로도 쓰는듯하다.
- Closing (클로징): Dilation 후에 Erosion을 적용하는 연산. 반면에 Closing은 Object내에 이미지를 패딩해주는효과가 있다.
위의 모든 단계는 커널(kernel, structuring element 또는 probe 라고도 함)을 이용하는데, 이는 입력이미지와 연산할 매개체를 의미한다. 예를 들어, 입력이미지가 A, 연산이 @, 커널이 B면, A@B의 연산을 한다. 주로 @은 위와 같이 종류가 다양하고, B에 해당하는 커널을 바꾸면서도 여러 종류의 연산이 가능하다.
알아야할 개념: Kernel, Fit, Hit, Miss. 위의 알고리즘을 설명하기 위해서는 아래의 이미지 처리시 개념을 선행해야한다.
- Kernel: 이미지 연산에 필요한 구조적인 요소(Structuring element). 이미지인데, 연산을 해줄 0또는 1로만 이뤄진 이미지를 의미한다. 입력이미지를 덮어가면서 연산할 이미지를 의미한다[3].
- Fit: Kernel 이미지의 픽셀이 모든 입력이미지에 커버가 되는 경우.
- Hit: Kernel 이미지의 픽셀 중 하나라도, 입력이미지에 커버가 되는 경우.
- Miss: Kernel 이미지의 픽셀 중 하나라도 입력이미지에 커버가 되지 않는 경우.
Erode (침식): 주로 오브젝트의 사이즈를 조금 줄일 때 사용
침식은 수학적인 표현으로는 주로 "$\ominus $"라는 표현을할 수 있다. 침식(Erode)은 모든 형태변형 알고리즘 연산과 같이 2개의 값을 요구한다. 하나는 입력이미지(침식 시킬 이미지, $A$), 또 하나는 커널(Kernel, $B$)이다. A를 커널 B로 침식시킨다는 표현은 $A\ominus B$로 표현할 수 있다.
erosion은 다음의 규칙으로 연산한다.
$A\ominus B$: A와 커널 B가 fit이면 1, 아니면 0을 채운다. 이 과정을 kernel의 중앙부가 0인 지점에따라 계산한다.
import cv2 as cv
import numpy as np
image = np.array(
[
[0,0,0,0,0],
[0,1,1,1,0],
[0,1,1,1,0],
[0,1,1,0,0],
[0,1,0,0,0],
],
np.uint8
)
kernel = np.array(
[[0,1,0],
[1,1,1],
[0,1,0]
],
np.uint8
)
cv.erode(image, kernel)
그림으로 표현하면 다음과 같다. 커널의 중심부가 배경(0)인 지점을 모두 순회하면서 hit인 부분이 있으면 모두 0으로 바꿔준다.
그러면 가운데 하나만 1만 남게된다.
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]], dtype=uint8)
응용 예) 주로 두꺼운 펜으로 작성한 글씨나, 번져서온 이미지인 경우 Erode을 시키면 세밀해진 이미지를 얻을 수 있다.
erosion은 다음의 규칙으로 연산한다.
$A\ominus B$: A와 커널 B가 fit이면 1, 아니면 0을 채운다. 이 과정을 kernel의 중앙부가 0인 지점에따라 계산한다.
import cv2 as cv
import numpy as np
image = np.array(
[
[0,0,0,0,0],
[0,1,1,1,0],
[0,1,1,1,0],
[0,1,1,0,0],
[0,1,0,0,0],
],
np.uint8
)
kernel = np.array(
[[0,1,0],
[1,1,1],
[0,1,0]
],
np.uint8
)
cv.erode(image, kernel)
그림으로 표현하면 다음과 같다. 커널의 중심부가 배경(0)인 지점을 모두 순회하면서 hit인 부분이 있으면 모두 0으로 바꿔준다.
그러면 가운데 하나만 1만 남게된다.
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]], dtype=uint8)
응용 예) 주로 두꺼운 펜으로 작성한 글씨나, 번져서온 이미지인 경우 Erode을 시키면 세밀해진 이미지를 얻을 수 있다.
Dilation (팽창): 주로 오브젝트보다 약간 큰 사이즈의 이미지를 얻기 위함.
방법: Dliation도 erosion과 마찬가지로, kernel에 hit인 부분을 0으로 바꾸는 대신에, 1로 채워준다. 좀 더 큰 이미지의 영역을 확보하기 위함이다.
응용사례: Pill(알약)의 이미지보다 약간 큰 이미지 영역을 확보하기위해서, 이미지를 이진화(Binarization)시킨 다음, Dilation시켜서 좀더 큰 사이즈의 영역을 확보한다. 이는 약의 그림자 등 조금 큰 영역을 확보해서 Dection하는게 더 성능에 유리하기 때문에 이렇게 진행한다
Opening:주로 노이즈를 지우기 위해 사용.
응용 예: 이진화한 이미지에서 작은 점(노이즈)를 지울 때 사용한다. 또는 인공지능이 Segmentation한 영역에서 Background이미지에서 지저분하게 잘못 예측한 영역들을 오프닝으로 지울 수 있다.
Closing: 이미지 내 작은 구멍 및 점들은 채우기 위한 방법으로 사용.
Unet의 후속모델인 ResnetUnet을 이용하여 심장부와 폐부를 Segmentation했다. 그리고 그 예측결과 중에, predicted Mask처럼 구멍뚤린 부위를 후처리(Closing)을 이용해서 매꿔주어 성능을 향상시킬 수 있다.
[1] https://en.wikipedia.org/wiki/Binary_image
[2] https://homepages.inf.ed.ac.uk/rbf/HIPR2/erode.htm
[3] https://www.cs.auckland.ac.nz/courses/compsci773s1c/lectures/ImageProcessing-html/topic4.htm
[4] https://docs.opencv.org/4.x/d9/d61/tutorial_py_morphological_ops.html
'Data science > Computer Vision' 카테고리의 다른 글
[이미지 분할] Grabcut 사용법 (0) | 2023.04.26 |
---|---|
NMS(Non maximal supression) 계산하기, 파이썬 (0) | 2023.03.18 |
[5분 컷 이해] Grad-CAM 의 이해 (0) | 2022.07.17 |
python CV2, Image, Numpy 의 이미지 처리축 (0) | 2021.12.18 |
SSIM (Structural Similarity Index) 구하기 (0) | 2021.06.02 |