Python/파이썬 OpenCV 공부

[파이썬 OpenCV] 영상에 리매핑(remapping) 적용하기 - cv2.remap

AI 꿈나무 2020. 10. 7. 20:34
반응형

황선규 박사님의 <OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝>, 패스트 캠퍼스 OpenCV 강의를 공부한 내용을 정리해 보았습니다.

 


 

 

[파이썬 OpenCV] 어파인 변환과 투시 변환 - cv2.getAffineTransform, cv2.getPerspectiveTransform, cv2.warpPerspectivee

황선규 박사님의 , 패스트 캠퍼스 OpenCV 강의를 공부한 내용을 정리해 보았습니다. 어파인 변환과 투시 변환 1. 어파인 변환 - Affine Transform  어파인 변환은 영상의 이동, 전단, 확대, 회전을 조합��

deep-learning-study.tistory.com

 저번 포스팅에서 어파인 변환과 투시 변환에 대해 공부했습니다.

 이번에는 리매핑에 대해 알아보겠습니다.

 

리매핑(remapping)

 리매핑을 잘 활용하면 입력 영상을 직선이 아닌 곡선으로 표현할 수 있어 좀 더 자유도 있는 변환을 할 수 있습니다.

 

 리매핑은 영상의 특성 위치 픽셀을 다른 위치에 재배치하는 일반적인 프로세스 입니다.

 

 리매핑은 기하학적 변환을 맵핑합니다. 출력 영상의 x,y 좌표에서 픽셀 값을 입력 영상에서 참조할건데 어느 위치를 참조할 것인지 나타내는 map x와 map y 함수를 정의합니다.

 

  출력 영상의 좌표를 입력 영상의 어느 좌표를 참조해서 갖고올 것이냐를 설정해서 출력 영상의 모든 픽셀 값을 셋팅해 출력 영상을 만들어내는 방법입니다. 따라서 영상을 꿀렁꿀렁하게 하거나 휘게하는 것도 리매핑으로 할 수 있습니다.

 

 어파인 변환, 투시 변환을 포함한 다양한 변환을 리매핑으로 표현할 수 있습니다.

 

왼쪽은 이동변환, 오른쪽은 대칭변환 

 

 오른쪽은 대칭 변환을 리매핑으로 표현한 것입니다.

 

 대칭 변환은 x좌표를 (가로크기 -1 -x)로 매핑하였고 y좌표는 그대로 가져옵니다.

 

 x가 0이면 w-1이 되어 가로 끝 좌표를 참조합니다. 따라서 좌우 대칭이 됩니다.

 

 왼쪽은 이동 변환을 리매핑으로 표현한 것입니다.

 

 여기서 주의할 점은 (x-200)은 -200 이동하는 것이 아니라 x방향으로 200이동 한다는 의미입니다.

 

1. 리매핑 함수 - cv2.remap

 map1과 map2를 정의하면 cv2.remap 함수를 이용하여 리매핑을 할 수 있습니다.

 

cv2.remap(src, map1, map2, interpolation, dst=None, borderMode=None, borderValue=None) -> dst

• src: 입력 영상
• map1: 결과 영상의 (x, y) 좌표가 참조할 입력 영상의 x좌표. 입력 영상과 크기는 같고, 타입은 np.float32인 numpy.ndarray.
• map2: 결과 영상의 (x, y) 좌표가 참조할 입력 영상의 y좌표.
• interpolation: 보간법
• dst: 출력 영상
• borderMode: 가장자리 픽셀 확장 방식. 기본값은 cv2.BORDER_CONSTANT.
• borderValue: cv2.BORDER_CONSTANT일 때 사용할 상수 값. 기본값은 0.

 

 map1은 x좌표, map2는 y좌표를 의미합니다.

 

2. 삼각함수를 이용한 리매핑 예제

src = cv2.imread('tekapo.bmp')

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

h, w = src.shape[:2] # 입력 영상의 높이와 넓이 정보 추출

# np.indice는 행렬의 인덱스값 x좌표값 y좌표값을 따로따로 행렬의 형태로 변환해줌
map2, map1 = np.indices((h, w), dtype=np.float32)

# y좌표에 sin함수를 줬는데 파도처럼 꿀렁꿀렁하게 하기 위해서
# y좌표 값에 10픽셀만큼 꿀렁꿀렁 거릴 수 있도록.
# sin함수가 x좌표를 이용해서 파도를 만들기 위해 map1을 줌
# 적당한 값을 나눠서 여러번 꿀렁꿀렁 거리게
map2 = map2 + 10 * np.sin(map1 / 32)

# borderMode는 근방의 색깔로 대칭되게 해서 채워줌, 기본값은 빈 공간을 검은색으로 표현
dst = cv2.remap(src, map1, map2, cv2.INTER_CUBIC, borderMode=cv2.BORDER_DEFAULT

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()

cv2.destroyAllWindows()

 

 np.indices 함수로 행렬의 인덱스에 해당하는 x좌표값, y좌표값을 따로 따로 행렬의 형태로 변환해 줍니다.

 

 map2에 sin함수를 이용하여 파도를 만듭니다.

 

 borderMode는 cv2.BORDER_DEFAULT로 지정하여 빈 공간을 검은색이 아닌 주변 픽셀값을 대칭으로 설정했습니다.

 

 

리매핑 적용

 

반응형