[openCV] Morphology
openCV

[openCV] Morphology

오늘은 모폴로지에 대해서 정리해보자

 


What Is Morphology ?

 

보통 Binary Image에서 흰색으로 나타내지는

Obeject Area의 형태를 개선하기 위해 사용되는 기법


이런 모폴로지 기법도 오늘 글에서는 4가지 방법으로 갈린다.

 

1. Erosion

2. Dilation

3. Opening

4. Closing

 

하나 하나 알아보자

 

1. Erosion

 

Erosion 연산은 단어에서도 뜻을 알 수 있듯이 침식 연산이다.

 

말 그대로 이미지를 깎아내는 연산을 뜻합니다.

 

Binary Image에서 흰색 Object의 외곽 픽셀을 검은색으로 만들 수 있다.

 

노이즈를 제거하거나 붙어 있는 오브젝트를 분리하는 데 주로 사용하는 것이 Erosion 방식이다.

 

Erosion 연산을 위해서는 Structuring Element Kernel ( 구조화 요소 커널 )이라는 것이 필요하다.

 

Structuring Element Kernel은 0과 1로 구성된 커널을 의미한다.

 

Structuring Element Kernel에 대해서 한 가지 더 알아본다면

1이 채워진 모양에 따라서 십자형, 사각형, 타원형 등으로 표현할 수 있다.

 

Erosion 연산은 Structuring Element Kernel을 Input Image에 적용해서

연산을 하는 과정을 거친다.

 

 

출처: http://blog.daum.net/shksjy/314

사진과 함께 조금 더 자세히 알아보자

 

위 사진은 Erosion 연산의 예제이다

 

A 이미지에서는 하얀색 배경화면은 0을 의미하며 하늘색 배경화면은 1을 의미한다.

 

B는 1로 채워진 십자형 Structuring Element Kernel을 의미한다.

 

B의 중심부는 A의 픽셀을 훑는다.

 

B의 중심부 (Red Point)가 A의 각 픽셀을 훑을 때 Structuring Element Kernel이

온전히 A 이미지의 하늘색 픽셀에 채워지지 않는다면 

그 부분의 A 픽셀을 0에서 1로 바꾼다.

 

위 사진을 잘 보면 실제로 Structuring Element Kernel이 온전히 채워지는 부분만

1로 유지가 되는 것을 볼 수 있다.

 

이제 코드로 넘어가 보자

 

import cv2
import numpy as np 

img = cv2.imread("./erosion.png")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
img_result = cv2.erode(img_gray, kernel, iterations=1)

merged = np.hstack((img_gray, img_result))

cv2.imshow("merged", merged)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

하나 하나 살펴보자

 

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

cv2.getStructuringElement(shape, ksize [, anchor])

 

shape = Structuring Element Kernel의 shape

   - cv2.MORPH_CROSS : 십자가형
    - cv2.MORPH_ELLIPSE : 타원형
    - cv2.MORPH_RECT : 직사각형

 

ksize = kernel의 크기

 

img_result = cv2.erode(img_gray, kernel, iterations=1)

cv2.erode(src, kernel, anchor, iterations, borderType, borderValue)

 

src = input Image, Binary

kernel = Structuring Element Kernel

anchor(optional) = cv2.getStructuringElement()와 동일

iterations(optional) = Erosion 연산 적용 반복 횟수

borderType(optional) = 외곽 영역 보정 방법

borderValue(optional) = 외곽 영역 보정 값

 

[ Result ]

 

좌 : Input / 우 : Erosion

 

깔끔하게 침식 연산이 된 모습을 볼 수 있다.

 

 

2. Dilation

 

Dilation 연산은 팽창 연산이다.

 

위에서 다뤘던 Erosion 연산과 달리 Object의 주변을 확장하는 연산이다.

 

연산 방법도 그와 반대입니다.

 

Dilation 연산은 Kernel과 완전히 겹치지 않으면 1로 변경합니다.

 

그래서 주로 Erosion 연산에 의해서 작아진 이미지를 원래대로 돌리거나

인접해 있는 오브젝트들을 연결하여 하나로 만드는 데 사용합니다.

 

 

코드와 함께 봅시다.

 

import cv2
import numpy as np 

img = cv2.imread("./erosion.png")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
erosion = cv2.erode(img_gray, kernel, iterations=1)

diliation = cv2.dilate(erosion, kernel, iterations=1)
merged = np.hstack((erosion, diliation))

print(kernel)
cv2.imshow("merged", merged)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

주요 코드를 살펴봅시다.

 

diliation = cv2.dilate(erosion, kernel, iterations=1)

dst = cv2.dilate(src, kernel, dst, anchor, iterations, bordeType, borderValue)

 

모든 Argument는 cv2.erode와 동일하다.

 

[ Result ]

 

좌 : Erosion / 우 : dilation

확실히 Erosion Image에서 dilation Image가

Object의 크기가 두꺼워진 것을 볼 수 있다.

 

3. Opening

 

opening 연산은 Erosion 다음에 Dilation을 적용하는 것입니다.

 

그럼 이미지의 Noise를 적절하게 제거해줌과 더불어서

Erosion 연산의 단점 중 하나인 Object가 축소되는 것을 Dilation 연산이

Object의 크기를 키워줍니다.

 

 

바로 코드로 넘어가 보자

import cv2
import numpy as np 

img = cv2.imread("./erosion.png")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
img_result = cv2.morphologyEx(img_gray, cv2.MORPH_OPEN, kernel)

print(kernel)
merged = np.hstack((img_gray, img_result))
cv2.imshow("merged", merged)

cv2.waitKey(0)
cv2.destroyAllWindows()

주요 함수만 보자

 

img_result = cv2.morphologyEx(img_gray, cv2.MORPH_OPEN, kernel)

dst = cv2.morphologyEx(src, op, kernel, dst, anchor, iteration, borderType, borderValue)

 

src = Input Image, Video

 

op = Morphology 연산 종류

- cv2.MORPH_OPEN: 열림 연산

- cv2.MORPH_COLSE: 닫힘 연산

- cv2.MORPH_GRADIENT: 그레디언트 연산

- cv2.MORPH_TOPHAT: 탑햇 연산

- cv2.MORPH_BLACKHAT: 블랙햇 연산

 

kernel = Structuring Element Kernel

 

dst(optional) = Result Img Variable

 

anchor(optional) = Center Position Of Kernel

 

iteration(optional) = 연산 반복 횟수

 

borderType(optional) = 외곽 영역 보정 방법

 

borderValue(optional) = 외곽 영역 보정 값

 

[ Result ]

 

좌: Original / 우: Opening

 

Noise가 제거됨과 동시에 Object의 크기 역시 유지가 된 모습을

볼 수 있다.

 

 

4. Closing

 

closing 연산은 Dilation 연산을 먼저 적용한 후에 Erosion 연산을 적용하는 것입니다.



흰색 Object에 있는 작은 검은색 구멍들을 메우는 데에 사용합니다.

 

바로 코드를 살펴봅시다.

 

import cv2
import numpy as np

img_gray = cv2.imread("./test3.png")

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (11, 11))
img_result = cv2.morphologyEx(img_gray, cv2.MORPH_CLOSE, kernel)

merged = np.hstack((img_gray, img_result))

cv2.imshow("merged", merged)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

Opening 연산에서 cv2.morphologyEx()에 대해 설명이 있기 때문에

추가적인 설명은 생략한다

 

[ Result ]

 

좌: Original / 우: Closing 연산

Closing 연산한 결과를 보면 Original Image에서

검은색 구멍들이 메워진 것을 확인할 수 있다.

 

오늘도 끄-읕🙄

'openCV' 카테고리의 다른 글

[openCV] Hough Transform  (0) 2021.03.28
[openCV] Convolution & Mask (2)  (0) 2021.03.06
[openCV] Convolution & Mask (1)  (0) 2021.03.06
[openCV] Image Geometric Transformation (2)  (0) 2021.02.21
[openCV] Image Geometric Transformation (1)  (0) 2021.02.20