본문 바로가기
OpenCV/OpenCV-basic

모폴로지 연산(Morphology)

by kiimy 2021. 12. 12.
728x90
모폴로지 변환의 팽창(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 히트미스 연산
728x90

'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

댓글