본문 바로가기
유도항법제어/데이터기반제어

[PCA–4] PCA 예제: Eigenfaces

by 깊은대학 2021. 2. 24.

Extended Yale Face Database B 라는 얼굴 사진을 잔뜩 모아 놓은 사이트가 있다.

 

http://vision.ucsd.edu/~iskwak/ExtYaleDatabase/ExtYaleB.html

 

38명의 사람 얼굴을 9개의 자세 및 64개의 서로 다른 조명 조건에서 촬영한 사진으로 구성 되어있는데 Cropped Images에 있는 사진들은 높이가 192 픽셀 너비가 168픽셀로 된 흑백 사진이다. 이 얼굴 사진들은 연구 목적으로 자유롭게 사용할 수 있다.

 

 

PCA 알고리즘을 얼굴 사진 라이브러리에 적용하여 이른바 eigenfaces라는 축소 차원 좌표축을 구하고 사진 데이터를 eigenfaces로 표현하고 또 복원해 보도록 하자.

먼저 36명의 정면 얼굴 사진만을 추출하여 스냅샷 행렬을 만든다. 아래 그림에서 빨강색 박스로 표시된 나머지 2명의 얼굴은 평가용으로 남겨두고자 한다.

 

 

얼굴 데이터는 192×168 행렬로 되어 있으므로 벡터로 바꾸어야 한다. 얼굴 데이터 행렬에서 열(column)단위로 쌓아가면 32,256 차원을 갖는 벡터 x(i)를 만들 수 있다.

 

 

36명의 얼굴 사진에 대해서 차례로 데이터셋 x(1),x(2),...,x(36)R32,256을 만든다.

 

 

이제 PCA 알고리즘의 절차를 밟는다. 코드는 매트랩으로 작성했다.

(1) 데이터셋의 샘플 평균을 계산한다.

 

μ=1mi=1mx(i)

 

 

X = yaleFace(:, 1:36); % 32,256 by 36
mu = mean(X,2); 

 

평균 얼굴 모습은 다음과 같다.

 

figure(1), axes('position',[0  0  1  1]), axis off
imagesc(reshape(mu,n,m)), colormap gray  

 

 

 

(2) 모든 데이터셋을 다음과 같이 치환한다.

 

y(i)=x(i)μ

 

(3) 데이터셋의 스냅샷 행렬을 만든다.

 

Y=[y(1)y(2)y(m)] Rn×m

 

 

Y = X - mu;

 

(4) 스냅샷 행렬 Y의 특이값 분해(SVD, singular value decomposition)를 계산한다.

 

Y=UΣVT

 

 

[U, S, V] = svd(Y, 'econ');

 

특이값을 순서대로 나열해서 그림으로 보이면 다음과 같다.

 

Sd = diag(S);
figure(2), stem(Sd, 'o')

 

 

 

(5) d차원 (d<n) 직교 좌표축 wi, i=1,...,d 를 선택한다.

 

W=[w1w2wd]=[u1u2ud]=Ud Rn×d

 

축소 차원 d는 특이값을 이용하여 설계자가 미리 설정한 투사 오차보다 작도록 선정하면 된다.

 

 

다음 그림은 첫번째와 두번째 좌표축(여기서는 eigenfaces)을 이미지 데이터 192×168로 재변환하여 나타낸 것이다.

 

figure(3),  axes('position',[0  0  1  1]), axis off
imagesc(reshape(U(:,1),n,m)), colormap gray  

figure(4),  axes('position',[0  0  1  1]), axis off
imagesc(reshape(U(:,2),n,m)), colormap gray  

 

 

 

(6) 좌표축 wi, i=1,...,d 의 축성분을 계산한다.

 

zi=UdT(x(i)μ)

 

다음 그림은 3차원으로 축소했을 때 36개의 얼굴 데이터의 축성분을 표시한 것이다.

 

d = 3;
Z = U(:,1:d)'*Y;

figure(5),plot3(Z(1,:),Z(2,:), Z(3,:),'k.','LineWidth',2)
box, grid
xlabel('PC1'); ylabel('PC2'); zlabel('PC3')

 

 

 

(7) 차원이 축소된 좌표계에서 원래 차원의 좌표계로 데이터를 복원시키려면 다음과 같이 계산한다.

 

x^(i)=μ+Udzi

 

다음 그림은 첫번째 얼굴을 20차원으로 축소시킨 후 다시 원래 얼굴로 복원시킨 것이다.

 

d=20;
num_face = 1;
original_face = yaleFace(:, num_face); 
y_test = original_face - mu;

P_til = mu + U(:,1:d)*U(:,1:d)'*y_test;
figure(6), axes('position',[0  0  1  1]), axis off
imagesc(reshape(original_face,n,m)), colormap gray

figure(7), axes('position',[0  0  1  1]), axis off
imagesc(reshape(P_til,n,m)), colormap gray  

 

 

 

다음 그림은 첫번째 얼굴을 36차원으로 축소시킨 후 다시 원래 얼굴로 복원시킨 것이다. 원본과 구별할 수 없을 정도로 정확하다.

 

 

다음 그림은 eigenfaces을 계산할 때 사용하지 않은 데이터인 37번째 얼굴을 36차원으로 축소시킨 후 다시 원래 얼굴로 복원시킨 것이다.

 

 

원본과 비교하여 상당한 차이가 있는 것을 알 수 있다. 아무래도 32,256 차원의 이미지 공간을 36개의 eigenfaces로 표현하자니 일반적인 얼굴을 표현하는데에 한계가 있는 것으로 보인다. 하지만 Extended Yale Face Database B에 있는 38명의 사람 얼굴을 9개의 자세 및 64개의 서로 다른 조명 조건에서 촬영한 사진을 모두 사용하여 2,000 여개 이상의 eigenfaces를 구축한다면 보다 정확한 복원이 가능할 것으로 보인다.

 

 

 

댓글