Paper/Human

Face Reconstruction in the Wild

침닦는수건 2024. 7. 7. 21:50
반응형

내 맘대로 Introduction

 

2011년 논문. 오래돼도 이제 너무 오래된 논문이긴 하지만 눈에 띄어서 읽어봤다. 이 당시 기술치고 결과물이 육안으로 보았을 때 그럴 듯 해보이고 문제 정의가 꽤 괜찮았다고 생각한다. 이 당시 photo tourism이나 Build rome in a day 같은 in-the-wild 이미지 긁어 모아 reconstruction하는 논문이 대세였기 때문에 이를 face로 확장하고자 했던 것 같다. non-rigid한 대상을 같은 방식으로 복원할 수 없었기에 기존 논문들과 완전히 다른 방식으로 구현했다.

 

이 당시 딥러닝은 커녕, face mesh model 조차 없었던 시기였기 때문에 PCA를 주로 활용해서 구현했는데, 이렇게 생각해서 만들 수 있구나 하고 조금 감탄한 논문.

 

핵심 아이디어는 무표정의 template mesh를 하나 만들어 두고 (deformable 아님) 이 mesh를 이미지로부터 뜯어낸 normal을 갖고 보정해서 최종 face mesh를 만들어내는 방식.

 

여담으로 저자는 지금 워싱턴에서 교수를 하고 있는데 우연히 요즘 관심 갖고 있는 virtual try on 논문들을 쓰고 있어서 놀랐다. 사람들이 하는 생각은 진짜 똑같나 보다.

 

메모

intrinisic까지 같이 푼다면 난이도가 너무 높아지므로, weak perspective projection으로 가정하고 조명은 자연광 (광원이 엄청 멀리 있는 경우, 얼굴 전체에 적용되는 빛의 상태가 같다고 가정 함. 볼은 밝고, 이마는 어둡고 이런거 없음)

반사는 lambertian 난반사 없음.

in the wild 이미지기 때문에 얼굴 자세, 표정, 밝기가 다 다름.

이를 일단 normalization 안하면 승산이 없음

따라서 2D face keypoint와 3D template 상의 keypoint (둘 다 미리 찾아두는 것)으로 얼굴 영역만 이미지를 warping해서 뗘낸다. 

이 때 3D Template을 2D face에 fitting하게 되는데, weak perspective projection이므로 scale, rotation, translation을 찾음

SVD로 rigid transformation 찾기. (진짜 classic이다.)


떼어내면 위 그림의 첫번째 row처럼 됨.



이 부분이 핵심.

위 처럼 warped face는 다 동일한 pixel space에 있으므로,
N개 이미지 x HW개 pixel , (N x P) matrix를 만든 뒤 PCA를 적용한다. 

대상 얼굴을 표현하는 color space의 eigenvalue와 eigenvector를 pixel by pixel로 다 찾아내는 것. 

그 다음 highest eigenvalue부터 4개까지 잘라내고 나머진 버린다. 

그러면 M = UDVT ,dim(D)==4, 가 됨.

이 상태에서 한번 더 UDVT를 LS 형태로 변환함.

M = LS .

이게 표현하는 것은 얼굴을 표현하는 basis 중 가장 중요한 4개만 뽑아서 표현한, 핵심 얼굴이라고 볼 수 있다. 



따라서 보면 신기하게도, 조금 디테일은 뭉개졌지만, 모든 이미지에서 핵심 얼굴은 다 동일할 것이기 때문에 rank 4로 뽑아낸 얼굴은 웬만해서 같은 표정에 같은 geometry를 갖고 있다. 

(소름... 이렇게 생각한 것 너무 똑똑한 것 같다.)

이렇게 정리한 데이터 M = LS를 갖고 이젠 normal을 찾아낼 차례다. 

다시 말하면, 무표정 template mesh를 normal 갖고 보정해서 최종 mesh를 만드는 방식이므로, normal을 찾아내야 한다.

이 방법은 M = LS를 변형하는 것이다.

수식을 보면 S를 새로 찾는다고 했다. 근데 M = LS 는 이미 찾았는데 어떻게 찾는다는 건가??

열쇠는




여기에 있다. M = LS 사이에 어떤 A를 끼워넣을 수 있는 trick을 구사할 수 있다. 

L' = LA.inv ,   S' = AS로 새로 정의하고 S'를 새로 찾는 것이 수식(2)다. 

이 짓을 왜 하냐면, 이 때 새로 정의한 S'는 albedo * (1, nx, ny, nz)처럼 surface 표면 parameter를 표현하도록 유도하고 싶은데, 이 역할을 할 A를 찾아내는 것이다. 

다시.

M= LS의 값은 실제 물리적 값과 아무런 상관이 없다. 하지만 A를 컨트롤해서 S가 물리적으로 albedo와 normal을 표현하는 형태로 변형을 하고 싶은 것인다. LS에 정보가 들어있긴 하니까.

이렇게 만들기 위해서 수식(2)를 최적화 하는것.

S.T G S는 왜 등장하냐면, S'를 albedo(1, nx, ny, nz) 형태로 변형하는 A를 찾고 싶은거니까 결과 S'는 그 크기가 2여야 한다. 

S'의 크기를 2로 regularize 하기 위해 추가된 것.

가운데 G가 -1 1 1 1 이므로 1 nx ny nz인 S'는 S.T S 로 곱해졌을 때 크기가 0나와야 한다.
--------------------
이 때 하나의 trick으로 M 전체를 무조건 사용하는 것이 아니다. 즉 N개의 이미지 중 M-LS값이 특정 크기보다 큰 이미지 샘플(아마 표정 변화가 커서 그렇겠지)은 버린다. 

N 대신 선별된 k개로 작업함. -> 무표정에 가까운 애들만 모아서 작업하니까 성능 올라감.

이 최적화가 끝나면 pixel j마다 Sj albedo * (1, nx, ny, nz)를 알게 되는 것이고 모든 pixel에 대해서 찾았다면 face normal을 알게 되는 것. 

위 그림처럼 이미지의 모든 pixel을 다 모으면 face normal을 얻을 수 있다. 

한 번 이 작업을 하고, 나서 M-LS를 다시 업데이트 한다. 

만약 k개 선별이 달라졌다면 iterative 하게 다시 수행함.

normal은 활용해서 depth ,zx zy, zz로 변환 함. 

이 때 template mesh depth 같이 사용.
전체 과정을 다시 iterative하게 돌 수 있다. 

template mesh 대신 새로 찾은 mesh를 template으로 쓰면 더 정확할 것이기 때문이다. 

2D-3D alignment가 정확해지면 PCA도 정확해지고 뒤이은 작업도 당연히 개선된다. 

이는 수렴할 때까지 반복 가능. 

당연히 무표정 베이스이기 때문에 표정이 다양한 이미지가 많을 수록 에러가 커짐.


진짜 그럴 듯 하게 잘 나온다...어떻게 이렇게 했을까. 요즘 나오는 mesh recon보다 더 잘한 것 같다.




진짜 끝내준다.
반응형