이번 포스트에선 고전 물체 검출 알고리즘인 Haar Cascade Detector에 대해 다뤄보고자 합니다.
Haar Cascade 알고리즘은 2001년 발표된 특징 추출 기반 검출 알고리즘입니다.
이 때의 특징 추출은 고전적인 알고리즘을 기반으로 하며, CNN의 특징 추출과 유사하다 보시면 됩니다.
해당 검출기의 특징 추출은 검출기의 이름에서도 알 수 있다시피 Haar Filter라는 것을 기반으로 합니다.
Detector의 가장 기본인 Haar Filter부터 Detector 활용까지 천천히 다뤄보도록 하겠습니다.
Feature Extraction Using Haar Filter
가장 먼저 Haar Cascade Detector의 기본이되는 Haar Filter 기반의 Feature Extraction에 대해 다뤄보겠습니다.
Haar Filter란 물체 인식을 위해 사용되는 간단한 형태의 필터입니다.
Filter라는 이름에 걸맞게 해당 Filter를 통한 연산은 CNN의 Convolution Filter과 동일하게 동작합니다.
일반적인 Convolution Filter와 다른 점으론, Haar Filter는 흑/백 영역으로 나뉘어진 필터라는 것입니다.

위 이미지와 같이 직사각형의 간단한 모양에, 내부는 흑/백으로 이루어진 Filter를 Haar Filter라고 합니다.
Haar Filter는 흰색 영역 및 검은색 영역 각각에 속하는 모든 픽셀을 더해준 뒤, 이를 빼주는 방식으로 연산됩니다.
결과적으로 해당 Filter를 통해, 이미지 내의 특정한 특징을 강조하거나 패턴을 검출하는 과정을 수행합니다.

또한 한가지 구조를 지속적으로 사용하는 것이 아닌, 다양한 Filter를 정의하여 함께 사용하게 됩니다.
간단한 패턴을 기반으로 한 여러 패턴이나 다양한 스케일 혹은 방향을 통해 Haar Filter를 정의하게 됩니다.

Haar Filter를 사람의 얼굴과 같은 객체 탐지에서 사용될 수 있는 이유론, 얼굴의 패턴이 정해져있기 때문입니다.
사람의 생김새는 모두 다르지만, 얼굴의 패턴 자체는 대부분의 사람이 굉장히 유사하다고 볼 수 있습니다.
예를 들어 눈, 코, 턱, 입에 존재하는 명암으로 인한 패턴들이 데이터로 봤을 땐, 모든 사람들이 유사하기 때문입니다.
물론 얼굴의 일부가 아주 강한 빛이나 매우 어두운 상태로 가려져 있다면, 알기 어렵겠지만요.
이러한 Haar Filter는 연산 방식이 단순하고 직관적이기에, 쉽게 사용되고 빠르게 특징을 추출할 수 있습니다.
하지만 앞서 언급했던 것처럼 이미지의 밝기, 회전, 노이즈 등에 약하다는 단점 또한 존재하긴 합니다.
물론 대부분의 경우에선, Feature Extractor의 역할을 아주 잘 수행한다고 말할 수 있습니다!

이러한 Haar Filter를 기반으로 Detector를 만들 때, 위와 같은 정면을 보고 있는 얼굴 데이터 셋을 활용합니다.
해당 데이터 셋은 24 * 24 해상도를 가지며, 얼굴이 없는 Negative 이미지도 함께 사용합니다.
이렇게 전체적인 Haar Cascade 검출기의 단계 중 가장 기본이 되는 Haar Filter에 대해 알아보았습니다.
검출기는 이러한 Haar Filter를 통해, Sliding window 방식으로 이미지를 훑으며 특징을 추출합니다.
단, 여기서 문제가 한가지 발생하는데 바로 더하기 연산 과정에 중복 영역에 대해 정말 많이 수행되는 점입니다.
다음 파트에선 Haar Filter의 특징 추출 방식을 유지하며, 연산량을 줄이는 방법에 대해 알아보겠습니다.
Integral Image
Integral Image는 Haar Filter의 반복적인 더하기 연산의 횟수를 크게 줄일 수 있는 방법입니다.
이러한 알고리즘 개선을 통해 검출기의 속도 자체를 개선하여, 검출기는 15 fps로 물체를 검출할 수 있게됩니다.
물론 이러한 방법만을 통해, Haar 검출기의 속도가 매우 빠른 것은 아니며, 추가적인 방법 또한 존재합니다.
이 내용에 대해선 아래 Cascade 구조 파트에서 다시 한 번 다뤄보도록 하겠습니다.
다시 본론으로 돌아와서, Integral Image란 우리 말로 적분 이미지 혹은 통합 이미지의 뜻으로 사용됩니다.
대부분의 경우 적분 이미지라는 말을 많이 사용합니다.
해당 방법이 적분 이미지라는 명칭을 갖게된건, 동작 방식이 수학의 적분 방식을 갖기 때문입니다.
미분과 반대 개념인 적분을 계속 값을 누적하는 개념으로 이해해주시면 좋을 것 같습니다.
어떤 것을 누적하느냐? 라고 한다면 이는 이미지에 존재하는 픽셀을 해당 방향으로 누적한 것을 의미합니다.

위의 이미지에서, 어떤 Filter가 픽셀을 반복적으로 더한다고 했을 때, 이를 적분 이미지로 쉽게 구할 수 있습니다.
입력에 대해 우선적으로 적분 이미지를 만들어준 뒤, 필터 모양에 따라 맞추어 각 포인트를 계산해주면 됩니다.
예를 들어, 위에서 왼쪽 영역의 합은 14(3+2+5+4)이고, 적분 이미지에선 (46-20-22+10)로 계산됩니다.
2*2 크기의 Filter에선 큰 차이가 없지만, Filter 크기가 커지면 커질수록 차이가 크게 발생하게 됩니다.
적분 이미지에선 Filter의 크기가 어떻든 무조건 4개의 포인트를 더하고 빼주기만 하면 되기 때문입니다.
여러 크고 작은 비율과 크기의 Filter를 사용하기에 검출 속도를 위해선 무조건 사용해주어야겠죠?
그렇기에 Haar Cascade 검출기는 전처리 단계로, 입력에 대해 Integral Image를 생성하는 단계를 수행합니다.
다음 파트에선 Haar Filter와 Integral Image를 통해 추출된 특징으로 Classifier의 학습 과정을 다뤄보겠습니다.
Feature Selection Using Adaboost
앞서 Integral Image와 Haar Filter를 사용하여, 여러 스케일의 이미지에서 특징을 뽑는 과정을 거쳤습니다.
이후부턴 손쉽게 진행될 것 같지만 한가지 문제가 존재합니다. 바로 특징이 너무 과도하게 추출되었기 때문입니다.
Haar Cascade 검출기의 논문에선, 앞선 과정을 통해 추출된 특징이 약 180,000개라고 설명했습니다.
여기서 모든 특징이 유효하다면 상관없지만, 하지만 대부분이 검출에 의미 없는 특징이라는 문제가 있습니다.
그렇기에 우리는 어떠한 특징이 유효한지, 추출된 특징에서 선택해주는 과정을 거쳐야합니다.
이 때, 유효한 특징을 선택하기 위해 Adaboost를 활용합니다.
Adaboost 모델은 여러 개의 약한 분류기를 기반으로, 강한 분류기를 만들게됩니다.
일단 여러 약한 학습기들은 얼굴이 있는(positive) 이미지와 없는(negative) 이미지를 구분하도록 학습됩니다.
이 때, 하나의 약한 학습기는 하나의 Haar Filter를 통해 도출된 특징으로 학습됩니다.
앞서 정의한 Haar Filter들을 Filter 개수 만큼의 학습기에 매칭해서, 어떤 특징이 유효한지 찾는 과정을 거칩니다.
유효한 특징이라는 것은, 결국 객체(positive)와 배경(negative)을 잘 분류하는 학습기를 의미합니다.
이 과정에서 많은 특징이 버려지고, 지정한 객체를 분류하기 위해 효과적인 특징만이 남게됩니다.

예를 들어, 얼굴을 효과적으로 검출하는 Filter는 Adaboost를 통해 정의된 위 2개의 Filter라고 할 수 있습니다.
사람의 얼굴에서 눈 부분의 어두운 영역과 아래 밝은 영역 또는 양쪽 눈과 미간 사이의 영역이라고 할 수 있습니다.
여기까지 우리는 Filter를 정의하고, 이미지를 전처리하고, 특징을 추출하고, 특징을 선택하는 과정을 거쳤습니다.
다음 파트에선, 학습된 약한 학습기들을 순차적으로 이어서 구성하는 Cascade 구조에 대해 다뤄보겠습니다.
Cascade
머신러닝과 딥러닝에서 Cascade 구조란 순차적으로 만들어주는, 즉 직렬화의 개념을 의미합니다.
앞서 학습시킨 여러 약한 학습기를 기반으로, 여러 강한 학습기를 만든 뒤, 이를 순차적으로 구성하게 됩니다.
Haar Cascade 구조에서 사용되는 강한 학습기는, 학습된 N개의 약한 학습기를 기반으로 만들어집니다.
예를 들어, 20개의 약한 학습기가 있다면 성능이 낮은 순서대로 놓은 뒤, 5개/10개/15개/20개로 구성합니다.
이렇게 구성하는 이유는, Cascade 구조와 함께 물체 검출의 속도를 개선하기 위함입니다.
4개의 강한 학습기를 성능 순으로 놓은 뒤, 마지막 학습기에 도달하기 전에 negative로 분류되는 경우 무시합니다.
결과적으로 가장 성능이 좋은 강한 학습기까지 도달해서, positive 판정을 받은 경우에만 predict로 사용합니다.
직렬로 구성되면서도, 사이사이 머신러닝 앙상블의 개념을 함께 활용하면서 속도와 성능을 모두 잡도록 했습니다.

위의 이미지에서 보여지는 각 단계가 모두 하나의 강한 학습기라고 이해해주시면 될 것 같습니다.
가장 마지막 단계의 무겁고 정확한 학습기의 통과를 받기 전까지, 의미 없는 것들을 사전에 버려주게 됩니다.
이러한 단계가 길고 복잡할수록 검출 성능 자체는 올라가겠지만, 그에 따라 검출 속도 또한 낮아지게 됩니다.
이를 Trade-off 관계라고 하며, 이를 잘 조절하여 적절한 성능과 속도를 갖도록 구성해주어야 합니다.
이렇게 Cascade 구조까지 알아보았습니다. 다음 파트에선 마지막 검출 결과에 대해 다뤄보겠습니다.
Results
앞서 우리는 Haar Cascade의 전반적인 내용에 대해 다루었습니다.
약간 어려운 내용도 있었지만, 생각보다 쉬우면서도 좋은 아이디어로 구성된 검출기라는 것도 알 수 있었습니다.
앞서 구성된 검출기는 어떤 임의의 입력 이미지에 대해, 임의 크기의 윈도우를 이동시키며 타겟 객체를 검출합니다.
얼굴 데이터로 학습된 검출기는 얼굴만, 눈 데이터로 학습된 검출기는 눈만 검출하게 됩니다.

위의 이미지는 MIT+CMU 테스트 데이터를 통해, 검출 결과를 시각화한 이미지입니다.
대부분의 경우에선 얼굴을 잘 검출했지만, 일부 검출에 실패하거나 오탐 또한 존재하는 것을 확인할 수 있었습니다.
또한 Sliding Window 방식으로 인해, 하나의 얼굴에서 여러 예측이 도출될 수 있습니다.
이런 경우엔 서로 겹치는 N개의 예측 좌표를 평균내는 등의 후처리를 추가적으로 적용해주게 됩니다.
현재는 NMS와 같은 방법을 사용하지만, 과거엔 모든 예측 좌표를 평균내는 등의 방법을 사용한 것으로 보여집니다.
이렇게 우리는 고전 물체 검출기인 Haar Cascade Detector에 대해 다뤄보았습니다.
상세하진 않지만, 어느 정도 검출기가 학습되고 동작하는 방식에 대해선 알 수 있었을 것이라 생각됩니다.
이러한 Haar Cascade Detector는 현재 Python-OpenCV에서도 사용해볼 수 있습니다.
이번 포스트에선 다루지 않지만, 추후 기회가 된다면 OpenCV 기반의 예제 또한 다뤄보도록 하겠습니다.
이번 포스트에선 Haar Cascade Detector에 대해 다뤄보았습니다.
고전 검출 방법이기에 자료가 많아, 쉽게 이해하고 정리해볼 수 있었습니다.
제가 정리한 내용 중, 이해가 잘 안되거나 잘못된 설명이 있다면 언제든 피드백 부탁드립니다.
긴 글 읽어주셔서 감사합니다.
'Computer Vision' 카테고리의 다른 글
| Mean Shift, Histogram Backprojection 기반의 Object Tracking (5) | 2024.08.28 |
|---|---|
| RANSAC (RANdom SAmple Consensus) (5) | 2024.08.26 |