반응형
황선규 박사님의 <OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝>과 패스트 캠퍼스 OpenCV 강의를 공부하면서 내용을 정리해 보았습니다.
예제 코드 출처 : 황선규 박사님 github홈페이지
이전 포스팅에서 소벨 필터로 x방향, y방향 미분 값을 구했습니다.
이번에는 그래디언트를 이용해서 윤곽선을 검출해보겠습니다.
영상의 그래디언트 - Gradient
그래디언트는 함수 f(x,y)를 x축과 y축으로 각각 편미분(partial derivative)하여 벡터 형태로 표현한 것입니다.
x방향 미분과 y방향 미분을 따로 계산하고 벡터라는 것으로 묶은 것이 그래디언트입니다.
x방향 미분 성분과 y방향 미분 성분을 행렬 형태로 표현하여 한꺼번에 표현했습니다.
그래디언트의 크기와 방향은 다음 식으로 구할 수 있습니다.
실제 영상에서 그래디언트 크기는 픽셀 값의 차이, 변화량을 의미합니다.
그래디언트 방향은 픽셀 값이 가장 급격하게 증가하는 방향을 나타냅니다.
2D 백터의 크기 계산 함수 - cv2.magnitude
소벨 필터로 구한 x방향, y방향 미분 값을 cv2.magnitude에 입력값으로 설정하면 백터의 크기를 계산할 수 있습니다.
cv2.magnitude(x, y, magnitude=None) -> magnitude
• x: 2D 벡터의 x 좌표 행렬. 실수형.
• y: 2D 벡터의 y 좌표 행렬. x와 같은 크기. 실수형
• magnitude: 2D 벡터의 크기 행렬. x와 같은 크기, 같은 타입.
2D 백터의 방향 계산 함수 - cv2.phase
그래디언트의 방향을 계산할 수 있습니다.
cv2.phase(x, y, angle=None, angleInDegrees=None) -> angle
• x: 2D 벡터의 x 좌표 행렬. 실수형.
• y: 2D 벡터의 y 좌표 행렬. x와 같은 크기. 실수형.
• angle: 2D 벡터의 크기 행렬. x와 같은 크기, 같은 타입.
• angleInDegrees: True이면 각도 단위, False이면 래디언 단위
소벨 피터를 이용한 에지 검출 예제
예제 코드는 황성규 박사님의 깃허브를 참고했습니다.
src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit()
dx = cv2.Sobel(src, cv2.CV_32F, 1, 0) # float 형태의 미분값을 저장
dy = cv2.Sobel(src, cv2.CV_32F, 0, 1)
mag = cv2.magnitude(dx, dy) # 그래디언트 크기
mag = np.clip(mag, 0, 255).astype(np.uint8) # 255보다 커질 수 있으므로 saturate 연산
# 흰색과 검은색으로만 나타내는 윤곽선 생성
dst = np.zeros(src.shape[:2], np.uint8) # 0(검은색)으로 채워져 있는 영상 생성
dst[mag > 120] = 255 # 120은 임계값, 값을 적절하게 설정하면 내가 원하는 부분만 나타낼 수 있음
# dst = cv2.threshold(mag, 120, 255, cv2.THRESH_BINARY) # cv2 함수로 임계값 설정하기
cv2.imshow('src', src)
cv2.imshow('mag', mag)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
그래디언트 크기를 구하고 임계값 설정으로 에지를 얻게 되면 선이 너무 두껍다는 단점이 있습니다.
반응형