Опубликован: 20.08.2013 | Уровень: для всех | Доступ: платный | ВУЗ: Новосибирский Государственный Университет
Самостоятельная работа 4:

Классификация изображений с использованием bag-of-words методов

2. Обзор возможностей модуля features2d библиотеки OpenCV

2.1. Детектирование ключевых точек на изображении

Ключевое значение при построении признакового описания изображения имеет выделение (детектирование) характерных для изображения частей, в качестве которых можно рассмотреть, например, углы, ребра, регионы, соответствующие экстремумам интенсивности, и т.п. На алгоритмы, выделяющие такие особенности (ключевые точки), накладываются требования инвариантности относительно преобразований смещения и поворота, изменения масштаба и освещенности исходного изображения, а также точки положения камеры, с которой снят объект.

Одним из наиболее простых алгоритмов, который находит на изображении углы, является детектор Моравеца (Moravec) [15 ]. Основная идея алгоритма заключается в поиске точек, соответствующих максимуму изменения суммарной интенсивности в окрестности рассматриваемого пикселя при смещении данной окрестности на один пиксель в каждом из восьми принципиальных направлений (2 горизонтальных, 2 вертикальных и 4 диагональных). Основными недостатками данного детектора являются отсутствие инвариантности к преобразованию типа "поворот" и возникновение большого числа ложных срабатываний на диагональных ребрах. Детектор Моравеца обладает свойством анизотропии в 8 принципиальных направлениях смещения окна.

Детектор Харриса (Harris) [16 ] строится на основании детектора Моравеца и является его улучшением. По сравнению со своим предшественником он инвариантен относительно поворота, количество ложных срабатываний не велико за счет введения свертки с Гауссовыми весовыми коэффициентами. Однако результаты поиска значительно меняются при масштабировании изображения. Также существуют модификации детектора Харриса, которые учитывают вторые производные функции интенсивности (например, детектор Харриса-Лапласа (Harris-Laplace) [10 ]).

Детектор MSER (Maximally Stable Extremal Regions) [9 ] выделяет множество регионов, являющихся областями локального экстремума интенсивности, максимально устойчивыми к вариациям интенсивности в окрестности данных регионов. Детектор обладает свойством инвариантности относительно масштабирования изображения. Похожая идея поиска областей с экстремальными свойствами интенсивности пикселей, устойчивых к изменению масштаба, лежит в основе детекторов LoG (Laplacian of Gaussian [7 ]) и SIFT [8 ]).

Приведенные выше детекторы определяют расположение ключевых точек на изображении, используя только пиксели исходного изображения. Альтернативный подход состоит в том, чтобы использовать алгоритмы машинного обучения для тренировки классификатора точек на некотором множестве изображений. FAST-детектор (Features from Accelerated Test) [11 ] является типичным представителем данного класса детекторов.

Более подробное описание детекторов ключевых точек приведено в лекционной части курса.

В библиотеке OpenCV реализованы следующие детекторы: FAST [11 ], STAR [1 ], SIFT [8 ], SURF [2 ], ORB [12 ], MSER [9 ], GoodFeaturesToTrack [20 ], Harris [16 ], Dense [17 ], Simple blob [17 ]. Для использования детекторов особых точек необходимо подключить заголовочный файл opencv2/features2d/features2d.hpp и библиотеку features2d243(d).lib.

Классы, содержащие реализацию данных детекторов, унаследованы от базового абстрактного класса FeatureDetector. Рассмотрим подробнее методы данного класса.

Для создания детектора ключевых точек заданного типа используется метод create, возвращающий указатель на созданный объект класса детектора.

Ptr<FeatureDetector> FeatureDetector::create( 
          const string& detectorType) 
    

В качестве параметра данной функции передается строка, содержащая идентификатор типа детектора ("FAST", "STAR", "SIFT", "SURF", "ORB", "MSER", "GFTT" (GoodFeaturesToTrack), "HARRIS", "Dense", "SimpleBlob".

Для того, чтобы найти на изображении ключевые точки с использованием созданного детектора, необходимо вызвать метод detect

void FeatureDetector::detect(const Mat& image, 
          vector<KeyPoint>& keypoints, 
          const Mat& mask=Mat() ) const 
    

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

  • image – входное изображение
  • keypoints – массив найденных особых точек на изображении.
  • mask – маска, определяющая область изображения, в которой осуществляется поиск ключевых точек (элементами матрицы, описывающей маску, являются восьмибитные целые числа; ненулевые значения соответствуют области изображения).

Необходимо учесть, что при использовании детекторов SIFT и SURF требуется в исходном коде дополнительно подключить заголовочный файл opencv2/nonfree/nonfree.hpp, а в настройках проекта библиотеку nonfree243(d).lib. Наряду с этим вызвать функцию инициализации данного модуля: initModule_nonfree().

Рассмотрим пример функции, которая принимает на вход путь к изображению и возвращает найденные на данном изображении ключевые точки с использованием детектора SIFT.

// fileName – путь к изображению 
// keypoints – найденные ключевые точки на изображении 
void DetectKeypointsOnImage(const string& fileName, 
          vector<KeyPoint>& keypoints) 
{ 
  // загружаем изображение из файла 
  Mat img = imread(fileName); 
  // инициализируем модуль nonfree для использования 
  // детектора SIFT 
  initModule_nonfree(); 
  // создаем SIFT детектор 
  Ptr<FeatureDetector> featureDetector = 
        FeatureDetector::create("SIFT"); 
  // детектируем ключевые точки 
  // на загруженном изображении 
  featureDetector->detect(img, keypoints); 
} 
    

2.2. Вычисление детекторов ключевых точек на изображении

Дескриптором ключевой точки называется числовой вектор, характеризующий особенности изображения в окрестности данной точки. Изначально процедура построения дескрипторов применялась для нахождения соотвествия между ключевыми точками на разных изображениях. В результате построения формируется множество векторов признаков для исходного набора особых точек.

Одним из наиболее известных дескрипторов ключевых точек является SIFT (Scale Invariant Feature Transform) [8 ], в основе которого лежит идея вычисления гистограммы ориентированных градиентов в окрестности особой точки. Модификацией данного дескриптора является PCA-SIFT [6 ], который строится по той же схеме, используя окрестность большего размера. Для результирующего набора дескрипторов осуществляется снижение размерности векторов посредством анализа главных компонент (Principal Component Analysis, PCA) [5 ].

Дескриптор SURF (Speeded up Robust Features) [2 ] также относится к числу тех дескрипторов, которые одновременно выполняют поиск особых точек и строят их описание, инвариантное к изменению масштаба и повороту изображения. Фактически данный дескриптор представляет собой взвешенные значения градиентов и их абсолютных значений в 16 квадрантах, на которые разбита окрестность особой точки.

Цель создания дескриптора BRIEF (Binary Robust Independent Elementary Features) [4 ] состояла в том, чтобы обеспечить распознавание одинаковых участков изображения, которые были получены с разных углов обзора. При этом ставилась задача уменьшить количество выполняемых вычислений. В окрестности точки выбирается некоторым образом множество пар пикселей, и на данном множестве строится набор бинарных тестов, представляющих собой сравнение интенсивности в соответствующих пикселях. Результаты тестов объединяются в битовую строку, которая и является итоговым дескриптором ключевой точки. Более эффективной альтернативой дескриптору BRIEF является бинарный дескриптор ORB [12 ].

Подробное описание дескрипторов ключевых точек можно найти в лекционной части курса.

В библиотеке OpenCV реализовано вычисление следующих дескрипторов ключевых точек: SIFT, SURF, BRIEF, ORB, для использования которых необходимо в исходном коде приложения подключить заголовочный файл opencv2/features2d/features2d.hpp, а в настройках проекта библиотеку features2d243(d).lib

Классы, содержащие реализацию алгоритмов вычисления данных дескрипторов, унаследованы от базового абстрактного класса DescriptorExtractor. Рассмотрим подробнее методы данного класса.

Для создания объекта класса, предназаченного для вычисления дескрипторов ключевых точек заданного типа, используется метод create, возвращающий указатель на созданный объект класса

Ptr<DescriptorExtractor> DescriptorExtractor::create( 
        const string& descriptorExtractorType) 
    

В качестве параметра данной функции передается строка, содержащая идентификатор типа дескриптора ("SIFT", "SURF", "BRIEF", "ORB").

Для того чтобы вычислить дескрипторы ключевых точек на изображении с использованием созданного детектора, необходимо вызвать метод compute.

void DescriptorExtractor::compute(const Mat& image,
          vector<KeyPoint>& keypoints, 
          Mat& descriptors) const 
    

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

  • image – входное изображение.
  • keypoints – массив ключевых точек на изображении.
  • descriptors – вычисленные значения дескрипторов ключевых точек.

Необходимо учесть, что при использовании дескрипторов SIFT и SURF требуется дополнительно подключить заголовочный файл opencv2/nonfree/nonfree.hpp и библиотеку opencv_nonfree243(d).lib, а также вызвать функцию инициализации данного модуля: initModule_nonfree().

Рассмотрим пример функции, которая принимает на вход изображение и заранее найденные на нем ключевые точки и возвращает вычисленные значения SIFT дескрипторов в данных точках.

// img – исходное изображение 
// keypoints – ключевые точки на изображении 
// descriptors – вычисленные значения дескрипторов 
// ключевых точек 
void ComputeKeypointDescriptorsOnImage( 
        const string& fileName, 
        vector<KeyPoint>& keypoints, 
        Mat& descriptors) 
{ 
  // инициализируем модуль nonfree для использования 
  // дескрипторов SIFT 
  // (если данная функция ранее не вызывалась) 
  initModule_nonfree(); 
  // создаем объект класса вычисления SIFT дескрипторов 
  Ptr<DescriptorExtractor> descExtractor = 
        DescriptorExtractor::create("SIFT"); 
  // вычисляем дескрипторы ключевых точек 
  // на загруженном изображении 
  descExtractor->compute(img, keypoints, descriptors); 
} 
    
Александра Максимова
Александра Максимова

При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка?
 

Алена Борисова
Алена Борисова

В лекции по обработке полутоновых изображений (http://www.intuit.ru/studies/courses/10621/1105/lecture/17979?page=2) увидела следующий фильтр:


    \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 2 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array} - \frac{1}{9} \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 1 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array}

В описании говорится, что он "делает изображение более чётким, потому что, как видно из конструкции фильтра, в однородных частях изображение не изменяется, а в местах изменения яркости это изменение усиливается".

Что вижу я в конструкции фильтра (скорее всего ошибочно): F(x, y) = 2 * I(x, y) - 1/9 I(x, y) = 17/9 * I(x, y), где F(x, y) - яркость отфильтрованного пикселя, а I(x, y) - яркость исходного пикселя с координатами (x, y). Что означает обычное повышение яркости изображения, при этом без учета соседних пикселей (так как их множители равны 0).

Объясните, пожалуйста, как данный фильтр может повышать четкость изображения?

Сергей Кротов
Сергей Кротов
Россия
Дмитрий Донсков
Дмитрий Донсков
Россия, Москва, Московский Авиационный Институт