logo

기하학적 변환: 아핀 변환

아핀 변환 Affine transform

  • 선형 변환(a)과 평행 이동(b)을 합친 것
  • 변환 후에서 평행과 비율은 보존. 길이와 각도는 X
  • 영상의 이동, 전단, 확대, 회전을 조합
  • 3개의 점이 주어지면 아핀 변환을 결정할 수 있음

아핀 변환 Affine transform 이미지 2

평행 이동

image = cv.imread('balls.png') # 예제 이미지
image = cv.resize(image, (0, 0), fx=0.25, fy=0.25, interpolation=cv.INTER_AREA)
height, width, channel = image.shape  # 이미지의 높이, 너비, 채널 수

# 수평 이동
matrix = np.array([[1, 0, 50], [0, 1, 0]], dtype=np.float32)  # x축으로 50픽셀 이동
translated = cv.warpAffine(image, matrix, (width, height))  # 이미지 이동
show(translated)  # 이미지 출력

# 수직 이동
matrix = np.array([[1, 0, 0], [0, 1, 50]], dtype=np.float32)  # y축으로 50픽셀 이동
translated = cv.warpAffine(image, matrix, (width, height))  # 이미지 이동
show(translated)  # 이미지 출력

확대

wr = 2  # 가로는 2배
hr = 3  # 세로는 3배
matrix = np.array([[wr, 0, 0], [0, hr, 0]], dtype=np.float32)
resized = cv.warpAffine(
    image,
    matrix,
    (width * wr, height * hr), # 새로운 크기
    flags=cv.INTER_LANCZOS4) # 보간

회전

matrix = np.array([[0, -1, height], [1, 0, 0]], dtype=np.float32)  # 90도 회전 행렬
resized = cv.warpAffine(
    image,
    matrix,
    (height, width))  # 가로, 세로의 크기가 바뀜

회전 행렬 계산

center = width // 2, height // 2  # 이미지의 중심 좌표
angle = 45  # 회전 각도
ratio = 1  # 확대 비율
matrix = cv.getRotationMatrix2D(center, angle, ratio)  # 회전 행렬 계산
rotated = cv.warpAffine(image, matrix, (width, height))  # 이미지 회전
show(rotated)  # 이미지 출력

회전 행렬 계산 이미지 1

크기 맞추기 및 배경 채우기

cos = abs(matrix[0, 0])
sin = abs(matrix[0, 1])
new_width = int((height * sin) + (width * cos))  # 새로운 너비
new_height = int((height * cos) + (width * sin))  # 새로운 높이
image_center = (width // 2, height // 2) # 원본 이미지의 중심 좌표
matrix[0, 2] += (new_width / 2) - image_center[0]  # 새로운 x좌표로 이동
matrix[1, 2] += (new_height / 2) - image_center[1] # 새로운 y좌표로 이동

rotated = cv.warpAffine(
    image, matrix,
    (new_width, new_height), # 새로운 크기
    borderMode=cv.BORDER_CONSTANT, # 배경 색은 한 가지로
    borderValue=image[0, 0].tolist())  # 왼쪽 위 (0, 0)의 픽셀 값으로 배경을 채움

변환 행렬에서 회전각 역산

회전 행렬의 성분은 회전각 와 확대 비율 scale로 다음처럼 표현할 수 있음

matrix[0, 0] == scale * cos θ
matrix[0, 1] == scale * sin θ
# np.arctan2(y, x)는 tan의 역함수
angle_rad = np.arctan2(matrix[0, 1], matrix[0, 0])
angle_deg = np.degrees(angle_rad)
  • : 회전각

변환 행렬에서 회전각 역산 다이어그램 1

Previous
크로마 키 합성