[OpenCV] HOG 알고리즘 – 보행자 검출

이번 글에서는 HOG(Histograms of Oriented Gradients) 알고리즘에 대해 알아보겠습니다.

HOG 알고리즘은 2005년에 N. Dalal과 B. Triggs가 발표한 알고리즘 입니다. HOG는 그래디언트 방향 히스토그램을 의미합니다.

HOG 알고리즘은 다음 작동 방식을 가집니다.

1. 영상에서 64 X 128 크기 영상을 추출하여 계산합니다.

64 X 128 영상 추출

2. 그 다음 그래디언트를 계산하여 방향을 0 ~ 180도로 설정합니다. 예를 들어 소벨 연산을 한 뒤 cartToPolar 함수를 통해 그래디언트 크기를 계산합니다.

좌측 : x 그래디언트, 중간: y 그래디언트, 우측: 그래디언트 크기

3. 입력 영상을 8X8로 분할 합니다(가로 8개, 세로 16개). 이 8X8 부분 영상을 셀이라고 합니다.

4. 각 셀로부터 그래디언트 방향 성분에 대한 히스토그램을 구합니다.

5. 20도 기준으로 방향을 구분하면 9개의 빈으로 구성된 히스토그램이 만들어집니다.

6. 그리고 4개의 셀을 합쳐서 블록을 구합니다(블록크기 16  X 16). 블록을 1개의 셀만큼 이동하면서 정의하면 결과적으로 64 X 128영상에서는 블록이 가로 7개, 세로 15개, 총 105개의 블록이 추출될 수 있습니다. 블록 1개에는 36개의 실수 값으로 이루어진 방향 히스토그램 정보가 추출 되므로, 전체 블록에서 추출되는 방향 히스토그램 실수 값 개수는 105 X 36인 3780이 됩니다. 이 3780개의 값이 HOG 특징 벡터 역할을 하게 됩니다.

아래는 각 셀에서 계산된 그래디언트 방향 히스토그램을 표현한 영상입니다.

OpenCV에서는 HOGDescriptor 클래스를 사용하여 미리 계산된 HOG 기술자 정보를 제공합니다.

전체 코드는 아래와 같습니다.

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(void)
{
	bool bOpen = cap.open(".\\vtest.avi");
	if (cap.isOpened() == false)
	{
		cerr << "video open fail" << endl;
		return -1;
	}

	HOGDescriptor hog;
	hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

	Mat frame;
	while (true)
	{
		cap.read(frame);
		if (frame.empty())
		{
			cerr << "frame is empty" << endl;
			break;
		}

		vector<Rect> detected;
		hog.detectMultiScale(frame, detected);

		for (Rect r : detected)
		{
			Scalar c = Scalar(rand() % 256, rand() % 256, rand() % 256);
			rectangle(frame, r, c, 2);
		}

		imshow("frame", frame);

		if (waitKey(1) == 'x')
			break;
	}
	destroyAllWindows();

	return 0;
}