이번에는 PCA를 이용한 Eigenface에 대한 소개를 하겠다.
PCA에 대한 자세한 내용은 아래 링크에 설명해 놓았으니 참고하길 바란다.
https://hsyaloe.tistory.com/29
Eigenface
데이터셋 내의 얼굴 영상들의 고유 얼굴(Eigenface)를 찾는 알고리즘을 Eigenface라 한다. 이 알고리즘을 얼굴 인식 영역까지 확장할 수 있는데, 컴퓨터 비전에서 PCA를 가장 혁신적으로 활용한 사례라고 볼 수 있다.
그림 1. 은 10개의 얼굴 영상을 가진 간단한 얼굴 데이터베이스이다. 이는 [TFD_expression] 데이터셋에서 발췌한 것이다. 각 영상의 크기는 96 X 96 이다.
PCA를 이용해 얼굴인식을 하기 위해서 가장 먼저 할 일은 이들의 평균을 취해 평균 얼굴을 만드는 것이다. 이 때 평균 영상이 의미를 가지려면 몇 가지 조건을 만족해야 한다. ① 눈과 입의 위치가 대략 일치해야 하고 ② 조명이 비슷해야 한다. 현재 갖고 있는 데이터셋이 이들 조건을 만족한다면 그대로 사용 가능하고, 그렇지 않다면 얼굴을 검출한 후 적절히 변환해줘야 한다.
PCA를 이용해 Eigenface를 찾기 위한 알고리즘은 다음과 같다.
알고리즘
1. 입력 영상을 1차원 벡터 형태로 변환한다.
2. 평균 벡터를 구한다.
3. 입력 영상에서 평균 벡터를 빼서 모든 샘플을 원점 중심으로 옮긴다.
4. 공분산 행렬(Covariance Matrix)을 구한다.
5. 교유값(Eigenvalue)와 고유벡터(Eigenvector)를 구한다.
6. 교유값(Eigenvalue) 기준으로 상위 $d$개의 고유벡터(Eigenvector)를 선택한다.
7. 변환 행렬 $U$를 만들고, 이를 입력 벡터와 곱해 고유 얼굴(Eigenface)로 만든다.
1. 입력 영상을 1차원 벡터 형태로 변환한다.
각 얼굴 영상을 PCA의 입력으로 취할 수 있도록 벡터 형태로 변환한다. 단순히 2차원을 1차원으로 만들었다고 보면 된다. 이렇게 얻은 벡터를 $x_{i}$라고 하면, 이는 $MN$차원을 가진다. 총 $n$개의 얼굴 영상을 학습 집합 $X=\{x_{1}, x_{2}, \cdots, x_{n}\}$이라 하자.
2. 평균 벡터를 구한다.
학습 집합 $X=\{x_{1}, x_{2}, \cdots, x_{n}\}$ 로부터 평균 벡터 $\bar{x}$를 구한다. $\bar{x}$의 차원도 $MN$차원이다. 그림 2. 는 10개의 얼굴 평균 영상을 보여준다. 10명의 얼굴을 모아 평균을 냈지만, 사람 얼굴 형태가 잘 유지된다는 것을 알 수 있다. 왜 이런 현상이 생길까? 데이터베이스에 있는 $n$개의 얼굴 영상은 $MN$차원 공간의 점으로 간주할 수 있다. 얼굴 영상은 서로 다르지만 일정한 범위 안에서 변화를 겪기 때문에 이들 점은 특정 공간에 모여있게 되고, 평균 얼굴은 이들의 중간 지점에 위치하므로 얼굴 형태를 띠게 된다.
3. 입력 영상에서 평균 벡터를 빼서 모든 샘플을 원점 중심으로 옮긴다.
각 벡터에서 평균 벡터를 빼서 원점을 중심으로 분포하도록 변환한다.
4. 공분산 행렬(Covariance Matrix)을 구한다.
공분산 행렬은 $\Sigma=TT^{T}$로 구할 수 있다. $T$는 $X=\{x_{1}, x_{2}, \cdots, x_{n}\}$의 행 벡터를 열 벡터로 바꾼 $MN \times n$ 행렬이다. 이제 $\Sigma u^{T} = TT^{T}u^{T} = \lambda u^{T}$ 를 풀어 고유값 $\lambda$와 고유 벡터 $u$를 계산하면 된다. 이때 $\Sigma$ 가 $MN \times MN$ 이므로 현실적인 계산 문제가 발생한다.
그래서 영상의 크기에 해당하는 $MN \times MN$ 행렬 대신 영상의 개수에 해당하는 $n \times n$ 행렬을 이용하여 고유 벡터를 구한다. 이때 사용하는 식은 $T^{T}Tv^{T} = \lambda v^{T}$인데, $T^{T}T$는 $n \times n$ 이므로 훨씬 풀기 쉽다.
5. 고유값(Eigenvalue)와 고유벡터(Eigenvector)를 구한다.
6. 교유값(Eigenvalue) 기준으로 상위 $d$개의 고유벡터(Eigenvector)를 선택한다.
7. 변환 행렬 $U$를 만들고, 이를 입력 벡터와 곱해 고유 얼굴(Eigenface)로 만든다.
구한 공분산 행렬으로부터 교유값(Eigenvalue)와 고유벡터(Eigenvector)를 구하고 고유값이 가장 큰 $d$개만 선택한다. $T^{T}Tv^{T} = \lambda v^{T}$ 의 양변에 $T$를 곱하면 $TT^{T}Tv^{T}=\lambda Tv^{T}$ 를 얻는다. 이 식을 $TT^{T}(Tv^{T}) = \lambda(Tv^{T})$로 볼 수 있으므로 구하고자 하는 고유 벡터는 $u^{T}=Tv^{T}$가 된다. 선택된 고유 벡터를 고유값이 큰 순서에 따라 $u_{1}, u_{2}, \cdots, u_{n}$라 표기하고, 순서대로 변환 행렬 $U$에 넣는다. 고유 벡터 $u_{1}$은 $MN$ 차원으로서 영상의 크기와 같다.
그림 3. 은 3개의 고유 얼굴(Eigenface)를 보여준다. 오른쪽으로 갈수록 고유값이 작아진다. 고유값이 큰 벡터일수록 얼굴 형태가 뚜렷하다.
고유 얼굴의 활용
1. 얼굴 영상 압축
Eigenface 알고리즘의 출력 영상을 $Y = (y_{1}, y_{2}, \cdots, y_{d})$라 표기하면, $y_{i}$는 원래 벡터 $x$를 $u_{i}$ 축으로 투영한 값이다. 따라서 $y$를 역투영하면 원래 벡터 $x$를 구할 수 있다. 역투영 변환은 $U$의 역행렬로 수행할 수 있다. 이때 $U$는 $d \times MN$이므로 $U^{-1}$은 $MN \times d$ 크기의 의사 역행렬(pseudo-inverse matrix)이다. 이렇게 압축되었다 복원된 영상은 정보 손실이 있긴 있지만, 사람이 눈으로 인식할 수 있을 정도의 품질은 유지된다.
2. 얼굴 인식
$n$명의 서로 다른 사람의 얼굴을 담은 얼굴 데이터베이스 $X=\{x_{1}, x_{2}, \cdots, x_{n}\}$이 주어지면, $x_{i}$ 각각을 고유 얼굴 $y_{i}$로 변환하여 $Y = (y_{1}, y_{2}, \cdots, y_{n})$ 저장한다. 새로운 영상 $f$가 들어오면, 이를 벡터화 한 후 변환행렬 $U$를 곱해 출력 영상 $y$로 변환한다. 이제 $y$와 $y_{i}$의 거리 $d(y, y_{i})$를 계산한다. $q$번째 벡터 $y_{q}$가 가장 가깝다면 $q$번째 사람으로 인식한다. 만약 $d(y, y_{q})$가 임계값 이상이라면, 데이터베이스에 없는 사람으로 간주한다.
* 이 글은 <컴퓨터 비전(Computer Vision) 기본 개념부터 최신 모바일 응용 예까지> (오일석, 한빛아카데미) 책으로 공부하며 작성한 것이다.
'컴퓨터비전' 카테고리의 다른 글
[C++/OpenCV] 주파수 영역 필터링 / 저주파 및 고주파 통과 필터링 (0) | 2022.07.20 |
---|---|
[C++/OpenCV] 공간 주파수, 이산 푸리에 변환, DFT (0) | 2022.07.19 |
[OpenCV] PCA (Principal Component Analysis), 주성분 분석이란 무엇일까? (0) | 2022.07.18 |
[Python/OpenCV] 디렉터리에서 이미지 데이터셋 가져와 .npy 로 저장하기 (0) | 2022.05.10 |
[Python/OpenCV] Perspective Transform(투시 변환) (0) | 2022.05.06 |