본문 바로가기

인공지능/코드구현

벡터 선형 변환을 통한 이미지 축변환 (대칭/회전)


전체코드 및 결과에 대한 내용은 아래 GitHub 에 PDF 로 올려두었으니 참고해 직접 작성해보면 도움될 듯하다.


< 구현내용 >

내용에 앞서, 이 과정은 어느정도 선형대수의 이해가 선행되어야 이해하기 쉽다. 우선 추상적으로 문제를 정의하자면 아래 나타난 그림처럼, x, y의 2차원 평면좌표에 R 이라는 개체가 있고 이것을 노란색 선의 벡터기준으로 대칭이동 해야할 경우가 있다.

 

어떻게 노란색 선을 기준으로 이동시킬 수 있을까?

 

직관적으로 이해하기 쉬운 2차원 공간의 경우에는 아마 계산은 조금 번거롭지만 x, y 좌표 기준으로 노란선의 수직거리를 계산하고 이와 반대방향으로 똑같은 거리만큼 이동시키면 될 것이다. 

 

 

하지만 3차원부터 차원이 점차 늘어나면, 점점 계산이 복잡해지고 4차원부터는 그림조차 그려지지 않을 것이다. 하지만, 우리는 노란색 라인에 해당하는 벡터공간과 직교하는 벡터성분을 구해서 이를 아주 쉽게 이동시킬 수 있고 이러한 변환을 가능하게 만들어주는 것이 Transformation matrix 라고 한다.

 

우선 벡터공간에 직교하는 벡터성분을 구하기 위해서는 Gram-Schmidt Process 를 이해해야 한다. 간단히 설명하자면, 이 프로세스는 각각의 독립적인 N차원의 벡터성분을 서로 직교(Orthogonal)하도록 하는 벡터성분(크기가 1이므로, Orthonormal 이라고 함)으로 선형분리시켜준다. 아래는 3차원 벡터공간에 대해 직교벡터를 구하는 프로세스를 나타낸 것이다. 각 벡터성분 v1, v2, v3 를 직교하는 벡터성분 e1, e2, e3 로 변환하고 이 기저벡터를 통해 Transformation matrix를 구할 수 있다.

 

잠깐, 아래 수식을 설명하자면 "-(v*e)e" 부분은 벡터사영(vector projection)인데, u2를 예로 들면, v2에서 e1벡터공간으로 사영하는 벡터를 뺀다는 뜻이고, 해당 벡터간의 차이는 결국 두 끝점사이의 벡터이므로, 이는 곧 e1에 직교벡터를 의미한다.

 

 

즉, 아래 다이어그램과 같이 R -> R' 로 한번에 변환하기는 매우 어렵지만, 직교벡터 e공간(E)을 활용한 변환과정을 통해 손쉽게 이동시킬 수 있다. 이때 T_E 는 각 차원에 해당하는 identity matrix 와 유사하며, 어느 축을 기준으로 변환할 것인지 결정하는 역할을 한다. 아래 그림에서는 e_3 벡터축을 기준으로 대칭이동하는 예제로 볼 수 있다.

 

 

마지막으로 이러한 변환과정을 종합하면 아래와 같은 수식으로 나타날 수 있고, ( ) 괄호 안에 들어가있는 것을 Transformation matrix 라고 부른다.

 

위의 설명에 따라, 곰 그림을 특정 벡터공간을 기준으로 대칭이동 시키는 예제를 구현하면 결과 이미지는 아래와 같다. (전체코드는 위에 나와있는 Github repo 에 있다.)

import numpy as np
from numpy.linalg import norm, inv
from numpy import transpose
import matplotlib.pyplot as plt

# 아래 함수는 github repo 에 포함되어있음
from utils.bearNecessities import *


# 벡터의 직교화 E 와 선형변환을 위한 T 를 이용한 대칭행렬 계산
def build_reflection_matrix(bearBasis):
    E = gsBasis(bearBasis)
    # 주어진 벡터공간(bearBasis) 기준 y축 대칭이동 시키는 행렬 T
    TE = np.array([[1, 0],
                  [0, -1]])
    T = E @ TE @ inv(E)
    return T
    
# 팬더를 대칭시킬 임의의 기준 벡터공간
bearBasis = np.array([[1, -1],
                     [1.5, 2]])

# 선형변환 행렬 계산
T = build_reflection_matrix(bearBasis)

reflected_bear_white_fur = T @ bear_white_fur
reflected_bear_black_fur = T @ bear_black_fur
reflected_bear_face = T @ bear_face

ax = draw_mirror(bearBasis)

변환결과 이미지


 

728x90
반응형