Published on

고급컴퓨터그래픽스 | Motion Editing

앞서 들어가기 전에 관절들의 보간 방법 몇가지에 대해서 살펴 보자.

Linear Interpolation

선형보간으로 잘 알려진 방법 중 하나

lerp(a,b,t)=(1t)a+tblerp(a,b,t) = (1-t)a + tb

하지만 3차원 상에서 선형 보간은 rotation matrix 계산이 불가능하다.

그러면 벡터 간 v1,v2v_1, v_2 의 선형 보간은 가능할까?

가능은 하.지.만! 변화율이 일정하지 않음을 확인할 수 있다.

그래서 이에 대한 대안으로 Slerp가 있다.

Slerp

Spherical Linear intERPolation의 약어로 orientation에 있어서 선형 보간 방법이라고 생각하면 쉽다.

slerp(R1,R2,t)=R1(R1TR2)t=R1exp(tlog(R1TR2))slerp(R_1, R_2, t) = R_1({R_1}^T R_2)^t = R_1exp(t\cdot{log(R_1^TR_2)})

R1R_1R2R_2의 차이( R2R1R_2 - R_1 )를 interpolate/scale rotation 후에 R1R_1에 더한 것이라고 보면 된다.

지수함수와 로그함수의 사용 이유는 전 시간에 언급되었던,

  • exp: rotation vector ➡ rotation matrix
  • log: rotation matrix ➡ rotation vector

Interpolation of Postures

두 포즈의 gap filling으로 아래와 같이 활용된다.

  • root position: linear interpolation
  • root & joint orientation: slerp

Time Warping

포즈 외 포즈 간의 시간 또한 가능하다

원데이터는 일정 속도로 걷는 데이터인데, 특정 구간에서 점점 빨라지는 모습을 볼 수 있다.

Uniform sampling

pos(t)=(1α)pos(ti)+αpos(ti+1),whereα=ttiti+1tipos(t) = (1-\alpha)pos(t_i) + \alpha pos(t_{i+1}), where \alpha = \frac{t - t_i}{t_{i+1}-t_i}

예를 두 배 빠르게 하고 싶을 경우 원본 데이터에서 2배 적게 추출하면 된다. 2개 프레임 중 가장 첫 번째씩으로 뽑으면(?) 된다. m1(t)=m2(2t)m_1(t) = m_2(2*t)

반면 느린 경우 데이터를 별도로 interpolate 하는 과정이 필요하다.

Motion difference

frame간 posture의 차이이다. 이러한 차이를 motion displacement mapping이라고 한다.

Motion Warping

posture difference를 활용해서 특정 keyframe 포즈를 살려서 warping 한다.

end effector 위치에 있어서 매우 효과적이다.

이미지에서 보이는 것처럼 걷다가 특정 프레임중 앉는 프레임을 다음과 같이 구현할 수 있다.

Motion Stitching

Motion warping이 특정 프레임에서 이와 다르게 stitching은 서로 다른 두 가지의 모션을 시작과 끝을 연결해서 하나의 데이터처럼 보이게 하는 방법이다.

이어 붙이기 전에 TrT_r 동안 interpolate을 하게 된다. s(t)함수의 경우 ease-in-out function으로 자연스러운 마감을 보이는데, 이와 관련해서는 종류가 다양하지만 여기선 생략하겠음.

Root alignment

물론 무조건 시작과 끝을 계산하는 것도 중요하지만, root 부분이 최대한 위치와 방향이 일치하는 전처리가 선행되어야 한다.

let's say, m1m_1's last posture root info: (pn1,Rn1)(p_n^1, R_n^1) and m2m_2's first posture root info: (p02,R02)(p_0^2, R_0^2)

먼저 alignment difference를 계산하고, pad=pn1p02p_{ad} = p_n^1 - p_0^2 Rad=Rn1(R02)TR^{ad} = R_n^1(R_0^2)^T

적용하면 된다..! pi2=p02+Rad(pi2p02)+padp_i^2 = p_0^2 + R^{ad}(p_i^2-p_0^2)+p^{ad} Ri2=RadRi2R_i^2 = R^{ad}R_i^2

이 때 RadR_{ad}는 up-vector(global frame)에 대한 회전만 남겨야 한다..!

Motion Blending

걸었다가 몰래 걷기, 후에 다시 걷기 동작을 구현할 때 아래와 같다.

Non-uniform resampling

blending시 linear interpolation를 하게 되면 fps라던가 속도에 있어서 discontinuity가 발생한다.

그래서 계산된 blend 부분에서 Non-uniform resampling을 하게 되는데, time scaling 시에 위 time warping에서 다뤘듯, scale factor를 단순히 hermite basis function과 같은 함수로 대체하면 된다..!

Spacial Alignment

stitching에서 다룬 비슷한 내용. root의 방향과 위치 외 joint들을 별도로 interpolate을 할 필요성이 있다. 각 관절이나 endeffector의 위치 경우 local frame을 기준으로 계산한다.

Wrapup & Conclusion

중간중간 gif파일이 프로젝트로 구현했던 것들이다. 사실 나름 잘? 구현했다고 생각했는데, 이 날 발표 때 엄청나게 혼났다...ㅠㅠ TDD 안한게 컸었고 모른다고 몰라!! 저 기능들을 기존 UI에 있던 프로젝트와 연결하거나 사용자 입력이 들어갔어야 했는데, 시간이 없어서 결과물에 포커스를 맞췄다. 무엇보다 2주 안에 저걸 다 구현하는게 벅찼고(대학원생..) 그냥 내 선에서 최대한 구현해본 것 같다.

Reference

아래는 이번 시간에 배운 내용을 코드로 확인해볼 수 있는 repository.

Authors