본문 바로가기
OpenCV/OpenCV-basic

모폴로지 연산(Morphology)

by kiimy 2021. 12. 12.
모폴로지 변환의 팽창(dilation)과 침식(erosion)을 기본 연산으로 사용해
고급 형태학을 적용하는 변환 연산

입력 이미지가 이진화된 이미지라면 팽창과 침식 연산으로도 우수한 결과를 얻을 수 있다.
하지만, 그레이스케일이나 다중 채널 이미지를 사용하는 경우 더 복잡한 연산을 필요

▪ 모폴로지(Morphology) 연산이란?

• 영상을 형태학적인 측면에서 다루는 기법

• 다양한 영상 처리 시스템에서 전처리(pre-processing) 또는 후처리(post-processing)

  형태로 널리 사용

• 수학적 모폴로지(mathematical morphology)

 

▪ 구조 요소(Structuring element)

  • 모폴로지 연산의 결과를 결정하는 커널, 마스크, 윈도우

# 만약 세로방향으로만 침식 or 팽창 하고싶다면
# ksize(가로, 세로) 가로를 작게하고 세로를 크게
# kernel
se = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 3))
'''
cv2.MORPH_RECT 사각형 모양
cv2.MORPH_CROSS 십자가 모양
cv2.MORPH_ELLIPSE 사각형에 내접하는 타원
'''

dst1 = cv2.erode(src, se)

dst2 = cv2.dilate(src, None)

침식 Erosion 

구조 요소가 객체 영역 내부에 완전히 포함될 경우 고정점 픽셀을 255로 설정
객체 크기는 감소 & 배경은 확대

- 작은 크기의 객체(잡음=noise)제거

- 객체 내부의 홀(구멍)이 점점 커짐

팽창 Dilation

구조 요소와 객체 영역이 한 픽셀이라도 만날 경우 고정점 픽셀을 255로 설정
객체 크기는 증가& 배경은 감소

- Noise가 커진다

- 객체 내부의 홀(구멍)이 채워짐


열림(Opening)

opening = dilate(erode(src))

# cv2.morphologyEx

cv2.morphologyEx(원본 배열, 연산 방법, 구조 요소, 고정점, 반복 횟수, 테두리 외삽법, 테두리 색상)
opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=5)

src = cv2.imread('ch07\\images\\rice.png', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

dst1 = np.zeros(src.shape, np.uint8)

bw = src.shape[1] // 4
bh = src.shape[0] // 4

# adaptiveThreshold 사용해도 되는데 느림
for y in range(4):
    for x in range(4):
        src_ = src[y*bh:(y+1)*bh, x*bw:(x+1)*bw]
        dst_ = dst1[y*bh:(y+1)*bh, x*bw:(x+1)*bw]
        cv2.threshold(src_, 0, 255, cv2.THRESH_OTSU, dst_)


cnt1, _ = cv2.connectedComponents(dst1)
print('cnt1:', cnt1)

dst2 = cv2.morphologyEx(dst1, cv2.MORPH_OPEN, None)
# open = 보통 noise를 제거할 때 사용
#dst2 = cv2.erode(dst1, None)
#dst2 = cv2.dilate(dst2, None)

cnt2, _ = cv2.connectedComponents(dst2)
print('cnt2:', cnt2)

'''
cv2.connectedComponents(image, labels=None, connectivity=None, 
                        ltype=None) -> retval, labels

흰색 덩어리의 개수를 정수 형태로 return( retval, labels)
retval 덩어리 개수 + 1 의 형태로 나옴
labels = np.ndarray 나오고 각 덩어리에 label 값부여됨
'''

cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()

침식 연산을 적용한 다음, 팽창 연산을 적용

침식 연산으로 인해 밝은 영역이 줄어들고 어두운 영역이 늘어난다.
 
opening = 줄어든 영역을 다시 복구하기 위해 팽창 연산을 적용하면 반대로 어두운 영역이
               줄어들고 밝은 영역이 늘어남
 

스펙클(speckle)이 사라지면서 발생한 객체의 크기 감소를 원래대로 복구

= 노이즈를 제거하는데 유용

 

Adative Threshold / morphologyEX

닫힘(Closing)

closing = erode(dilate(src))

closing = cv.morphologyEx(thresh, cv.MORPH_CLOSE, kernel, iterations=5)

팽창 연산을 적용한 다음, 침식 연산을 적용

팽창 연산으로 인해 어두운 영역이 줄어들고 밝은 영역이 늘어난다.

 

closing = 늘어난 영역을 다시 복구하기 위해 침식 연산을 적용하면 밝은 영역이 줄어들고

             어두운 영역이 늘어남

객체 내의 작은 구멍이나 검은 점을 없애는데 도움


 

Gradient(Edge 반환)

gradient = dilate(erode(src)) - erode(dilate(src))

gradient = cv.morphologyEx(thresh, cv.MORPH_GRADIENT, kernel, iterations=1)

팽창 연산자와 침식 연산자의 조합

입력 이미지에 객체의 가장자리가 반환 = iterations= 낮을 수록 edge 반환

* 연산 방법( op )

cv2.MORPH_DILATE 팽창 연산
cv2.MORPH_ERODE 침식 연산
cv2.MORPH_OPEN ( O ) 열림 연산
cv2.MORPH_CLOSE ( O ) 닫힘 연산
cv2.MORPH_GRADIENT ( O ) 그레이디언트 연산
cv2.MORPH_TOPHAT 탑햇 연산
cv2.MORPH_BLACKHAT 블랙햇 연산
cv2.MORPH_HITMISS 히트미스 연산

'OpenCV > OpenCV-basic' 카테고리의 다른 글

특징 검출  (0) 2021.12.24
이미지 연산, 배열 정합(addWeighted)  (0) 2021.12.12
opencv-VideoCapture, VideoWriter  (0) 2021.12.11
opencv-HSV, YCrCb(특정 색 추출)  (0) 2021.12.11
opencv-findContours  (0) 2021.12.11

댓글