논문리뷰를 하던 도중 글에서 Bag-of-visual-words라는 개념이 나왔다. 기존에 Bag-of-words라는 개념은 NLP에서 공부한 적이 있어서 알고 있었지만, visual이 들어간 용어는 처음 봤기에 호기심을 못 참고 찾아봤다.
(느낌상 비슷할 것 같긴 했지만 그래도 정확히….)
분류(Classification)
우리가 보통 이미지를 분류하는 문제를 다룰 때 어떻게 해왔는가? 물론 지금은 딥러닝이 많이 발전해서 end-to-end모델에 이미지를 원본(또는 약간의 수정) 그대로 넣어 분류문제를 해결하지만, 과거에 머신러닝(ML, 딥러닝이 아닌 머신러닝)을 이용하던 때에는 이미지를 컴퓨터(모델)가 이해할 수 있도록 변환시킨 후 모델에 대입했었다. 따라서 이미지를 표현(Represent)하는 여러 방법들이 연구되었고, 그 중 하나가 바로 Bag-of-Visual-Words기법이었다. computer vision분야에서 좋은 성과를 선보였던 Bag-of-Visual-Words기법에 대해 알아보자.
(편의상 BOVW로 칭하자. 너무 길어요ㅠㅠ)
Bag-of-Words(BOW)
BOVW를 알기 전에 먼저 BOW(Bag-of-Words)에 대해 알아보자. BOW는 자연어처리(NLP, Natural Language Processing)에서 흔히 사용되는 기법으로 문서(Document)들을 분류할 때 자주 사용한다. 문서들의 뭉치에 포함되어 있는 단어들의 분포를 파악하여 해당 문서가 어떤 문서인지 분류하는 기법을 말한다. 예를 들어 논문(문서)에 ‘세포’, ‘바이러스’, ‘DNA’ 등의 단어들이 자주 나오면 이 논문은 ‘생물학’과 관련된 내용으로 분류하게 되고, ‘CO2’, ‘NH4’ , ‘O2’ 등의 화학기호가 많이 나오면 ‘화학’과 관련된 내용으로 분류하게 된다. 문서들의 뭉치에서 나온 단어들을 가방(Bag)에 넣고 단어들의 사용 횟수(분포)를 파악하여 각 클래스별로 분류를 짓는 방식이다.
BOW와 마찬가지로 BOVW 또한 이러한 방식을 모방한 기법인데, NLP에서는 ‘단어’이용해 문서를 표현했다면 Computer Vision(CV)에서는 이미지를 통해 추출되는 ‘특징(feature)’을 이용하여 이미지를 표현한다는 차이가 있다. (물론 마지막에는 BOW나 BOVW 둘 다 컴퓨터가 이해할 수 있도록 벡터vector로 변환한다)
Bag-of-Visual-Words(BOVW)
가정(Hypothesis)
본 개념의 이해를 돕기 위해 가정을 한 가지 세워보자.
지금부터 우리는 (강아지, 사람, 자동차) 이 3가지의 클래스에 대해 ‘분류’작업을 실시한다고 가정하자. 그러면 한 이미지에 대해 해당 이미지가 3가지 클래스 중 어느곳에 속하는지 알아내야 하는데, 그 과정을 생각하면서 개념을 이해해보자.
이미지를 분류하기 위해서는 각 클래스별로 특징이 필요하다. 즉, 클래스를 구별할 수 있는 ‘기준’이 있어야한다.
- 강아지 : 4개의 다리가 있고(1), 귀가 비교적 크고(2), 털이 많다(3)
- 사람 : 2개의 다리가 있고(1), 2개의 팔이 있으며(2), 직럽보행의 모양을 띈다(3)
- 자동차 : 4개의 바퀴가 있고(1), 창문이 있으며(2), 모서리가 많다(3)
(물론 이 밖에도 각 클래스의 특징들은 더 많다.)
이제 각 클래스별로 드러나는 특징들을 모두 합친 후 가방(bag)에 넣어보자.
Bag-of-Viusal-Words가 완성되었다. 참 간단하죠~?
한 가방에 모든 특징들을 합치긴 했지만 클래스별로 특징들의 분포가 다르게 나타날텐데, 이것이 BOVW의 핵심이다.
과정(Processing)
이제 BOVW가 어떻게 만들어지는지 좀 더 구체적으로 알아보자.
(위 예시에서는 간단하게 다리, 바퀴 등 눈으로 봤을 때 구분이 되는 큰 특징들을 말했지만, 사실은 좀 더 복잡하다.(컴퓨터는 의외로 우리보다 똑똑하지 못하다….)
BOVW는 세 가지의 과정을 거쳐서 완성된다.
- 이미지에서 Keypoints를 추출하고(feature detection)
- 추출한 Keypoints을 설명하는 vector로 표현하고(feature description)
- 표현된 수많은 description(vector) 중 대표할 수 있는 몇 개의 대표값을 설정(codebook generation)
- 각 이미지들에 대한 대표값들의 히스토그램 만들기(Histogram)
1. Feature Detection
- 이미지들로부터 특징점(keypoints)을 추출한다. 다양한 feature detection 알고리즘이 있지만 흔히 SIFT 알고리즘을 이용한다.(SIFT 알고리즘은 특허문제로 더이상 opencv-python에서 사용 불가…)
- 알고리즘을 적용하면 특징점(x,y)을 얻을 수 있다.
- 여기서 특징점(Keypoints)는 픽셀(pixel)이 될 수도 있고, 더 넓은 구역(patch)가 될 수도 있다.
- 모든 사진에 대해 Keypoints를 추출한다.
2. Feature Description
- Keypoints를 추출했다면 위에 설명한 바와 같이 대부분 (x,y)좌표로 된 값들이다.(이미지는 격자로 되어있음)
- (x,y)좌표로는 해당 점이 무엇을 나타내는지 컴퓨터가 알 수 없다(이미지에서 단순히 위치정보만 포함).
- 하나의 ‘기준’을 토대로 해당 점을 설명하는 vector를 만든다(의미부여). –> Description
- 다양한 descriptor가 있지만 대표적으로 SIFT나 HOG등이 있다.(SIFT는 detector와 descriptor 둘 다 가능)
3. Codebook Generation
- 모든 Keypoints에 대해 Description을 만들면 비슷한 부분들이 많다. 따라서 그 중 대표적인 Description들만 추출하기 위해 비지도학습 알고리즘을 적용하여 k개의 대표값(Codebook)을 추출한다.
- 비지도학습으로 K-means Clustering 알고리즘을 많이 사용한다.
- k값은 결국 대표값(Codebook)의 size을 뜻하고, 결국 BOVW의 Size가 된다.
4. Histogram
- 완성된 Codebook을 토대로 각 이미지마다 히스토그램을 만든다.
- Codebook의 크기가 k라면, 히스토그램의 x축의 크기(bin의 개수)도 k가 된다.
완성(Complete)
짜란~ 각 이미지들에 Bag-of-Visual-Words를 적용한 결과다. 물론 BOVW가 단순히 이미지를 다르게 표현하는 방법 중 하나지만, 이미지의 차원(Dimension)을 축소시키는 효과도 있다. 즉, 이미지에서의 특징이 더 잘 드러나도록 도와주고 기계학습을 진행할 떄 계산량도 대폭 감소시켜준다.
BOVW 적용
그렇다면 BOVW를 위에서 가정했던 ‘분류’문제에 어떻게 적용시킬까? 원리는 간단하다. 이미지마다 BOVW으로 표현을 하면 Codebook의 분포가 다양하게 나타날텐데, 같은 클래스라면(강아지, 사람, 자동차) 각 클래스마다 Codebook의 분포가 비슷한 양상을 보일 것이다. 따라서 분류기(베이지안, SVM 등)를 이용해 해당 클래스의 Codebook 분포 양상을 파악하고 새로운 이미지가 들어오면 유사도를 측정해 분류를 실시한다.(실제 적용은 다음 포스트에…ㅎ)
요약