dtw-python 응용하기
내가 해야 하는 것은 두가지 캐릭터 모션데이터를 align 하는 것이다. 이 과정에 고전적으로 DTW를 사용해서 나도 DTW를 이용하기로 했다.
DTW에는 세가지 입력이 필요하다. 명칭은 달라질 수 있으나 dtw-python quick start에서 사용했던 용어를 그대로 쓰면,
1. query: 첫번째 타임시리즈 =X = x1, x2 ...., xm
2. template: 두번째 타임시리즈 = Y = y1, y2, ... yn
3. non-negative 거리 계산 함수 = f (xi,yi)
여기서 거리 계산함수는 query와 template의 매 item들 간에 적용된다.
1. 퀵스타트 소스코드 분석
quickstart 소스코드를 한줄 한줄 분석해보자.
#index를 만든다.
idx = np.linspace(0,6.28,num=100)
#index를 이용해서 noise가 포함된 sin 곡선을 만든다.
query = np.sin(idx) + np.random.uniform(size=100)/10.0
#index를 이용해서 cos 곡선을 만든다.
template = np.cos(idx)
# DTW를 수행한다.
alignment = dtw(query, template, keep_internals=True)
## 정렬 결과를 draw 한다.
alignment.plot(type="threeway")
## Rabiner-Juang type VI-c unsmoothed recursion 으로 DTW를 수행하고 스탭 패턴을 프린트 한다.
dtw(query, template, keep_internals=True,
step_pattern=rabinerJuangStepPattern(6, "c"))\
.plot(type="twoway",offset=-2)
## 결과를 그려준다.
print(rabinerJuangStepPattern(6,"c"))
rabinerJuangStepPattern(6,"c").plot()
스탭패턴은 다음과 같이 출력된다.
2. 코드 변환 및 적용
일단 내가 해야하는 작업은 query와 template를 1차원이 아닌 다차원으로 늘이는 작업이다.
캐릭터 애니메이션은 보통 24개의 조인트를 쓰고 각자 3dof를 가지고 있다 치면 총 72 dof를 가지게 된다.
이제 고민이 되는 부분은 alignment를 하기 위한 distance function을 어떻게 잡냐인데...
일단은 각 조인트 별 position distance를 다 합한걸 distance function이라고 하면 약간 편하게 작업이 가능할 것 같다.
이걸 어떻게 파이썬 안에서 구현할지에 대해서 고민해보자.
일단 논문 12페이지를 보면,
https://www.jstatsoft.org/article/view/v031i07
관련된 내용이 나온다.
일단 차원수는 c라고 지칭하게 된다.
dtw는 기본적으로 유클리디언 로컬 디스턴스를 가정한다. 그러면 별 문제가 없을 것 같다.
이후에는 그냥 query와 template를 다차원으로 확장해서 쓰면 되는 모양. 해보자.
import numpy as np
## A noisy sine wave as query
query = np.random.randn(200, 3)
template = np.random.randn(200, 3)
## Find the best match with the canonical recursion formula
from dtw import *
alignment = dtw(query, template, keep_internals=True)
## Display the warping curve, i.e. the alignment curve
alignment.plot(type="threeway")
3차원의 랜덤 query와 template를 만든 후 dtw를 적용한 결과를 plot 해보면 아래와 같다.
이제 이걸 캐릭터 조인트에 적용해볼 차례다.
이번 포스팅은 여기까지.