Home OpenCV HOG 알고리즘
Post
Cancel

OpenCV HOG 알고리즘

해당 포스팅은 OpenCv 4로 배우는 컴퓨터 비전과 머신러닝 (황선규 저)를 보고 공부하며 개인적인 용도를 위해 정리한 글이다.

HOG (Histogram of Oriented Gradients) 알고리즘

  • 사람이 서있는 영상에서 그래디언트를 구하고 그래디언트 크기와 방향 성분을 이용하여 사람이 서있는 형태에 대한 특징 벡터를 정의한다.
  • 특징 벡터를 머신 러닝의 일종인 서포트 벡터 머신 (SVM, Support Vector Machine) 을 이용하여 입력 영상에서 보행자 위치를 검출하는 방법이다.

계산 방법

  • 기본적으로 $(64, 128)$ 영상에서 그래디언트를 계산한다.
  • 크기와 방향성분으로 계산하며 방향성분은 $0^{\circ}$부터 $180^{\circ}$까지로 설정한다.
  • 입력 영상을 $(8, 8)$ 크기 단위로 분할하며 해당 크기의 영상을 셀 (cell) 이라고 정의한다.
  • $(64, 128)$개로 분할한 영상에서 가로로 8개, 세로로 16개의 셀을 만들 수 있고, 각 셀별로 그래디언트 방향 성분을 $20^{\circ}$로 설정하여 총 9개의 빈 (bin) 을 갖는 히스토그램을 만든다.
  • 이 때, 인접한 4개의 셀을 블록 (block) 이라고 정의한다.
  • 하나의 블록엔 4개의 셀이 있고 하나의 셀에는 9개의 히스토그램이 있으므로 하나의 블록에서는 총 36개의 실수로 된 히스토그램 데이터가 나온다.
  • 블록은 가로세로 방향으로 한 칸씩 움직이며 정의하므로 $(64, 128)$ 영상에선 총 가로 7개, 세로 15개의 블록을 정의할 수 있으며, 히스토그램의 총 갯수는 $15 * 7 * 36 = 3780$개가 된다.
  • 이 $3780$개의 히스토그램은 $(64, 128)$크기의 영상의 특징 벡터를 의미한다.
  • 해당 특징 벡터들을 보행자의 특징 벡터, 보행자가 아닌 특징 벡터로 학습한 SVM을 통해 검출을 시도한다.

cv::HOGDescriptor

  • 미리 정의 된 기술자 정보를 반환하는 정적 멤버 함수 getDefaultPeopleDetector()를 제공한다.
    • 정적 멤버 함수이므로 cv::HOGDescriptor::getDefaultPeopleDetector()의 형태로 선언한다.
  • 객체를 검출하기 위해선 훈련 된 SVM 분류기 계수를 setSVMDetector() 로 등록해야한다.
  • cv::HOGDescriptor::detectMultiScale()는 두 개의 형태로 정의 되어있는데, foundWeights 변수에 검출 된 객체의 신뢰도를 전달하냐의 차이이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "opencv2/opencv.hpp"

int main(void)
{
    cv::videoCapture cap("path/to/video");

    if (!cap.isOpened())
    {
        std::cerr << "the video file is not opened!" << std::endl;
        return 1;
    }

    cv::HOGDescriptor hog;  // 검출기 객체 생성
    hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());  // 객체에 검출 분류기 전달

    cv::Mat frame;

    while(1)
    {
        cap >> frame;  // 영상을 frame 에 전달

        if (frame.empty())
        {
            std::cerr << "the video is ended." << std::endl;
            break;
        }

        std::vector<cv::Rect> detected;
        hog.detectMultiScale(frame, detected);  // 보행자 검출

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

        cv::imshow("frame", frame);
        
        if (cv::waitKey(10) == 27)
        {
            break;
        }
    }

    cap.release();

    return 0;
}
This post is licensed under CC BY 4.0 by the author.

OpenCV cascade 얼굴 검출

OpenCV QRCode 검출