Опубликован: 02.09.2013 | Уровень: для всех | Доступ: платный
Самостоятельная работа 8:

Детектирование пешеходов

< Самостоятельная работа 7 || Самостоятельная работа 8: 12345

2.3. Метод бегущего окна и HOG-детектор

В данном разделе рассматривается использование HOG-признаков для детектирования объектов на изображении. Однако сначала рассмотрим, каким образом можно решить задачу классификации изображений при помощи HOG-дескриптора. Пусть нам требуется определить, является ли заданное изображение изображением пешехода или нет. Другими словами, мы хотим классифицировать изображения на те, которые содержат искомый объект (пешехода), и не содержат его. Для этого, мы можем поставить в соответствие изображению его признаковое описание, полученное с помощью HOG, а затем использовать алгоритмы машинного обучения, для непосредственного осуществления классификации. Поскольку большинство алгоритмов обучения с учителем работают в пространстве признаков фиксированной размерности, вектора HOG-признаков для различных изображений должны быть одинаковой длины, а, следовательно, классифицируемые изображения должны быть одинакового размера. Более того, для обеспечения приемлемого качества решения данной задачи предполагается, что данные изображения содержат объекты одинаковых (близких) размеров, которые занимают одну и ту же область изображения.

Теперь перейдем непосредственно к решению задачи детектирования. В том случае, если выполнены изложенные выше предположения относительно размеров и расположения объектов, то данная задача эквивалентна задаче классификации и, следовательно, может быть решена описанным методом. Однако, как правило, это не так. Для обобщения на такие случаи может использоваться метод бегущего окна, который сводится к рассмотрению задачи детектирования как множества задач классификации. Пусть мы хотим осуществить поиск на изображении всех объектов заданного размера w \times h. Для этого с некоторым шагом по вертикали dy и по горизонтали dx рассмотрим прямоугольные области изображения размера w \times h с верхним левым углом с координатами (i \cdot dx, j \cdot dy),i=\overline{0,n},j=\overline{0,m} и для каждого из них произведем классификацию. Таким образом, по изображению как бы "бежит" окно размера w \times h . Дальнейшее обобщение метода на случай поиска объектов разного размера возможно за счет многократного масштабирования изображения и осуществления детектирования описанным выше методом.

Рассмотрим функционал библиотеки OpenCV для вычисления HOG-признаков и детектирования методом бегущего окна. Метод compute класса HOGDescriptor позволяет извлекать признаки всех или некоторых окон детектирования для заданного изображения:

void compute(const Mat& img, 
     vector<float>& descriptors, 
     Size winStride=Size(), 
     Size padding=Size(), 
     const vector<Point>amp; locations=vector<Point>()) const; 
     

Рассмотрим параметры данного метода.

  • img – изображение, матрица типа CV_8UC1 или CV_8UC3. Во втором случае в каждой точке градиент вычисляется независимо по каждому каналу, и из них выбирается вектор наибольшей длины.
  • descriptors – вектор, в который последовательно будут записаны признаковые описания заданных окон детектирования.
  • winStride – шаг окна детектирования по горизонтали и вертикали. По умолчанию используется winStride, равный размеру ячейки HOG.
  • padding – размер рамки, добавляемой к изображению. Перед запуском метода бегущего окна вокруг (справа, сверху, слева, снизу) изображения может быть сгенерирована рамка, прежде всего, с целью обеспечения возможности поиска частично видимых объектов на границе изображения. Размер границы будет выровнен до размеров кратным наибольшему общему делителю шага окна детектирования и размера блока HOG по соответствующему направлению. Плюс к этому будет добавлена рамка в один пиксель, для вычисления градиента в граничных пикселях. Генерация данной рамки производится путем отражения пикселей изображения, т.е., например, если значения цвета пикселей изображения обозначить за abcdefg, то изображение с рамкой слева и справа будет выглядеть следующим образом: gfedcb|abcdefg|fedcba.
  • locations – положения окон детектирования, для которых требуется вычислить векторы HOG-признаков. По умолчанию признаки вычисляются для всех окон.

В OpenCV реализован HOG-детектор, использующий в качестве классификатора машину опорных векторов с линейным ядром. Обученный линейный SVM-классификатор представляется вектором коэффициентов уравнения разделяющей гиперплоскости в пространстве признаков. Перед тем, как осуществлять детектирование необходимо с помощью метода setSVMDetector задать используемую модель классификатора:

void setSVMDetector(InputArray svmdetector); 
  • svmdetector – матрица-вектор, содержащая коэффициенты разделяющей гиперплоскости. Длина вектора должна либо быть на единицу больше длины HOG-дескриптора одного окна детектирования, либо равняться ей. В первом случае последним элементом svmdetector является значение свободного члена.

Библиотека OpenCV содержит обученные для решения задачи детектирования пешеходов линейные SVM-модели, которые можно получить с помощью методов getDefaultPeopleDetector (обучена на базе INRIA [4, 9], размер окна детектирования 64x128) и getDaimlerPeopleDetector (обучена на базе Daimler [5, 10], размер окна детектирования 48x96).

Для непосредственного детектирования объектов фиксированного размера (т.е. без использования масштабирования изображения) служит метод detect:

void detect(const Mat& img, 
      vector<Point>& foundLocations, 
      vector<double>& weights, 
      double hitThreshold=0, 
      Size winStride=Size(), 
      Size padding=Size(), 
      const vector<Point>& searchLocations=vector<Point>() 
     ) const; 
  • img – изображение, матрица типа CV_8UC1 или CV_8UC3 .
  • foundLocations – координаты верхних левых углов окон детектирования, классифицированных как содержащие объект (срабатываний детектора).
  • weights – веса, присвоенные классификатором срабатываниям детектора (пропорциональны расстоянию признакового вектора от разделяющей SVM-гиперплоскости). Можно трактовать данный параметр, как числовую характеристику надежности решения соответствующей задачи классификации: большие значения обозначают большую надежность.
  • hitThreshold – минимальное значение веса (см. параметр weights), при котором происходит срабатывание детектора.
  • winStride – шаг окна детектирования по горизонтали и вертикали.
  • padding – размер рамки, добавляемой к изображению.
  • searchLocations – положения окон детектирования, по умолчанию используются все.

Для детектирования объектов различного размера (путем масштабирования изображения) предназначен метод detectMultiScale :

void detectMultiScale(const Mat& img, 
                    vector<Rect>& foundLocations, 
                    vector<double>& foundWeights, 
                    double hitThreshold=0, 
                    Size winStride=Size(), 
                    Size padding=Size(), 
                    double scale=1.05, 
                    double finalThreshold=2.0, 
                    bool useMeanshiftGrouping=false) const; 
                

Параметры img, foundLocations, foundWeights, hitThreshold, winStride, padding по смыслу совпадают с аналогичными параметрами метода detect . Рассмотрим оставшиеся параметры:

  • scale – мультипликативный шаг изменения масштаба. Исходное изображение последовательно уменьшается в 1,scale,scale^2,...,scale^t , …, раз, тем самым позволяя осуществлять детектирование более мелких объектов с использованием той же SVM-модели. Масштабирование прекращается либо в том случае, когда полученное изображение хотя бы по одному измерению становится меньше окна детектирования, либо по совершению nlevels (см. параметры конструктора класса HOGDescriptor ) итераций.
  • finalThreshold – параметр группировки (non-maximum suppression) срабатываний детектора на всех рассматриваемых масштабах. Значение данного параметра зависит от типа используемой группировки.
  • useMeanshiftGrouping – параметр, определяющий использовать ли группировку методом сдвига среднего (Mean Shift), или группировку на основе разбиения на классы эквивалентности. В связи с тем, что при использовании малого шага по масштабу возможны случаи, когда объект будет продетектирован несколько раз на различных масштабах. Следует отметить, что подобная ситуация возможна и при детектировании с малыми шагами окна на одном масштабе. Для того чтобы исключить множественные срабатывания детектора на один и тот же объект применяется группировка. В случае если useMeanshiftGrouping=false выполняется разбиение множества срабатываний детектора на классы эквивалентности. Эквивалентными считаются два прямоугольника r_1 и r_2 , у которых координаты углов отличаются меньше, чем на 0.1(min(r_1.width,r_2.width)+(min(r_1.height,r_2.height)). Затем, в классах, в которые попало больше чем finalThreshold прямоугольников, вычисляются "типичные представители", путем усреднения координат углов. Полученные прямоугольники фильтруются так, чтобы исключить ситуации, когда маленький прямоугольник находится в большом. На этом фильтрация считается выполненной. Метод сдвига среднего заключается в восстановлении плотности распределения точек в трехмерном пространстве (координаты центра прямоугольника и масштаб) с помощью ядерной оценки и нахождении максимумов плотности. В результате получается набор прямоугольников соответствующих максимумам и назначенных им весов. Все прямоугольники с весом меньшим или равным finalThreshold отсеиваются.

Перейдем к рассмотрению примера использования HOG-детектора.

#include <assert.h> 
#include "opencv2/core/core.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/objdetect/objdetect.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
 
using namespace cv; 
 
int main() 
{ 
    // загружаем тестовое изображение 
    Mat img = imread("testimg.jpg"); 
 
    // увеличиваем начальный масштаб изображения для 
    // поиска мелких объектов 
    resize(img, img, Size(2 * img.cols, 2 * img.rows)); 
 
    // параметры HOG-дескриптора и детектора 
    int nbins = 9; 
    Size cellSize(8, 8); 
    Size blockSize(16, 16); 
    Size blockStride(8, 8); 
    Size winSize(64, 128);     Size winStride(4, 4); 
 
    // создаем HOG-дескриптор/детектор 
    HOGDescriptor hog(winSize, blockSize, 
                      blockStride, cellSize, nbins); 
 
    // устанавливаем в качестве модели 
    // линейную машину опорных векторов, 
    // соответствующую размеру окна детектирования 64x128. 
    hog.setSVMDetector( 
                HOGDescriptor::getDefaultPeopleDetector()); 
 
    // проверяем соответствие количества коэффициентов 
    // гиперплоскости SVM и размера HOG-дескриптора 
    // одного окна детектирования 
    assert(hog.checkDetectorSize()); 
 
    // производим детектирование 
    vector<Rect> locations; 
    vector<double> weights; 
    hog.detectMultiScale(img, locations, weights, 
                         0.0, winStride, Size(), 
                         1.05, 2., true); 
 
    // уменьшаем изображение до начальных размеров 
    resize(img, img, Size(img.cols / 2, img.rows / 2)); 
 
    // отрисовываем срабатывания детектора на изображении 
    for (size_t i = 0; i < locations.size(); ++i) 
    { 
        Rect detection = locations[i]; 
        detection.x /= 2; 
        detection.y /= 2; 
        detection.width /= 2; 
        detection.height /= 2; 
        rectangle(img, detection, Scalar(0, 0, 255), 2); 
    } 
 
    // отображаем результат 
    namedWindow("detections"); 
    imshow("detections", img); 
    waitKey(); 
 
    destroyAllWindows(); 
    return 0; 
} 

Результат работы данного приложения на тестовом изображении из базы CalTech [6] приведен на рис. 15.1.

Результат работы HOG-детектора на тестовом изображении

Рис. 15.1. Результат работы HOG-детектора на тестовом изображении
< Самостоятельная работа 7 || Самостоятельная работа 8: 12345
Андрей Терёхин
Андрей Терёхин

Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции?

Демянчик Иван
Демянчик Иван

В главе 14 мы видим понятие фильтра, но не могу разобраться, чем он является в теории и практике.

" Искомый объект можно описать с помощью фильтра F= \lbrace f_{x',y'},x' \in \lbrace0, ...,w_f \rbrace , y' \in \lbrace 0,...,h_f \rbrace \rbrace "

Даниил Поволоцкий
Даниил Поволоцкий
Беларусь, Минск
Artem Bardakov
Artem Bardakov
Россия