При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка? |
Классификация изображений с использованием bag-of-words методов
3. Программная реализация
3.1. Разработка программы классификации изображений с использованием bag-of-words методов
3.1.1. Требования к приложению
На данном этапе предлагается разработать приложение, предназначенное для классификации изображений двух различных классов, предусматривающее возможность применения всех операций, перечисленных в разделе 2. К приложению предъявляются следующие требования:
- Ввод исходных данных (пути к папкам, содержащим изображения обоих классов; тип детектора и дескриптора особых точек; число слов в словаре дескрипторов ключевых точек) осуществляется через аргументы командной строки.
- Разбиение исходных данных на тренировочную и тестовую выборки случайным образом.
-
Выполнение следующей последовательности действий для тренировочной выборки:
- нахождение ключевых точек и вычисление их дескрипторов;
- обучение словаря;
- построение признакового описания изображений;
- формирование обучающей выборки и обучение классификатора "случайный лес".
-
Выполнение следующей последовательности действий для каждого изображения из тестовой выборки:
- нахождение ключевых точек и вычисление их дескрипторов;
- построение признакового описания;
- предсказание категории изображения с использованием обученного классификатора и вычисленных признаков;
- Вывод результатов классификации изображений на тестовой выборке.
3.1.2. Структура приложения
Приложение будет состоять из набора вспомогательных функций (auxiliary.cpp/h), основного модуля, содержащего реализацию основных стадий bag-of-words подхода к классификации изображений с использованием функций OpenCV (bow.cpp/h), и файла c исходным кодом основной функции (main.cpp). В рамках лабораторной работы предлагается реализовать функции из основного модуля; вспомогательные функции и код основной функции поставляется в реализованном виде.
Рассмотрим вспомогательные функции.
void GetFilesInFolder(const string& dirPath, std::vector<string>& filesList)
Заполняет массив filesList списком всех файлов с расширением *.jpg из директории dirPath. Рассмотрим параметры данной функции:
- dirPath – путь к директории, содержащей изображения
- filesList – список всех файлов с расширением *.jpg, содержащихся в данной директории
void InitRandomBoolVector(vector<bool>& mask, double prob)
Заполняет булевский вектор mask случайными значениями (true с вероятностью prob). Рассмотрим параметры данной функции:
- mask – булевский вектор, который должен быть заполнен случайными значениями;
- prob – вероятность того, что элементу булевского массива будет присвоено значение true.
Рассмотрим функции из модуля bow.cpp, которые необходимо реализовать в рамках лабораторной работы.
Mat TrainVocabulary(const std::vector<string>& filesList, const std::vector<bool>& isVoc, const Ptr<FeatureDetector>& keypointsDetector, const Ptr<DescriptorExtractor>& dExtractor, int vocSize)
Функция возвращает построенный словарь дескрипторов особых точек и принимает на вход следующие аргументы:
- filesList – список файлов;
- isVoc – маска, описывающая набор изображений из filesList, используемых для построения словаря;
- keypointsDetector – детектор ключевых точек;
- dExtractor – алгоритм, используемый для вычисления дескрипторов ключевых точек;
- vocSize – размер словаря.
Функция должна выполнять следующую последовательность действий:
- Создать объект класса BOWTrainer с размером словаря, равным vocSize и остальными параметрами по умолчанию.
-
Для каждого изображения из filesList, которое используется для построения словаря выполнить следующие действия:
- Прочитать изображение из файла.
- Продетектировать на изображении ключевые точки с использованием детектора keypointsDetector.
- Вычислить дескрипторы ключевых точек с использованием алгоритма dExtractor.
- Добавить вычисленные дескрипторы в набор дескрипторов, используемых объектом класса BOWTrainer для обучения словаря
- Обучить словарь.
Mat ExtractFeaturesFromImage( Ptr<FeatureDetector> keypointsDetector, Ptr<BOWImgDescriptorExtractor> bowExtractor, const string& fileName)
Функция возвращает признаковое описание изображения и принимает на вход следующие аргументы:
- keypointsDetector – детектор ключевых точек;
- bowExtractor – алгоритм, используемый для вычисления признакового описания изображения;
- fileName – входной файл.
Функция должна выполнять следующую последовательность действий:
- Прочитать изображение из файла fileName.
- Продетектировать на изображении ключевые точки с использованием детектора keypointsDetector.
- Вычислить признаковое описание изображения с использованием bowExtractor
void ExtractTrainData(const std::vector<string>& filesList, const std::vector<bool>& isTrain, const Mat& responses, const Ptr<FeatureDetector>& keypointsDetector, const Ptr<BOWImgDescriptorExtractor>& bowExtractor, Mat& trainData, Mat& trainResponses)
Функция предназначена для формирования обучающей выборки (trainData и trainResponses) для используемого алгоритма обучения с учителем; принимает на вход следующие аргументы:
- filesList – список файлов;
- isTrain – маска, описывающая набор изображений из filesList, используемых для обучения классификатора;
- responses – ответы (категории) для файлов из filesList;
- keypointsDetector – детектор ключевых точек;
- bowExtractor – алгоритм, используемый для вычисления признакового описания изображения;
- trainData (выходной параметр) – матрица, содержащая признаковые описания изображений из обучающей выборки;
- trainResponses (выходной параметр) – матрица, содержащая ответы (категории) для изображений из обучающей выборки.
Функция должна выполнять следующую последовательность действий:
- Вычислить число изображений в обучающей выборке (оно равно числу элементов в массиве isTrain, значение которых равно true).
- Инициализировать матрицу trainData для хранения признакового описания изображений из обучающей выборки: число строк равно числу объектов в обучающей выборке, число столбцов равно размерности пространства признаков (числу слов в словаре дескрипторов особых точек, которое соответствует числу строк в словаре, который использует bowExtractor), элементами матрицы являются числа с плавающей запятой одинарной точности.
- Инициализировать матрицу trainResponses для хранения ответов (категорий) объектов из обучающей выборки: число строк равно числу объектов в обучающей выборке, число столбцов равно 1, элементами матрицы являются 32-битные целые числа со знаком.
-
Для каждого изображения из filesList, которое используется для построения обучающей выборки:
- Вычислить признаковое описание изображения.
- Скопировать вычисленное признаковое описание изображения в соответствующую строку матрицы trainData.
- Скопировать ответ (категорию) изображения в соответствующий элемент матрицы trainResponses.
Ptr<CvRTrees> TrainClassifier(const Mat& trainData, const Mat& trainResponses)
Функция возвращает обученный классификатор "случайный лес" и принимает на вход следующие аргументы:
- trainData – матрица, содержащая признаковые описания изображений из обучающей выборки;
- trainResponses – матрица, содержащая ответы (категории) для изображений из обучающей выборки.
Функция должна выполнять следующую последовательность действий:
-
Создать структуру типа CvRTParams, описывающую параметры алгоритма обучения с учителем "случайный лес":
- Критерий остановки работы алгоритма – по числу итераций.
- Максимальное число деревьев – 200.
- Создать матрицу, описывающую типы входных переменных и ответа: число строк равно 1, число столбцов равно размерности пространства признаков (числу столбцов в матрице trainData) + 1, элементами матрицы являются 8-битные беззнаковые целые числа.
- Установить типы всех используемых признаковых переменных и ответа: все признаковые переменные являются вещественными (CV_VAR_ORDERED), ответ является категориальным (CV_VAR_CATEGORICAL).
- Создать объект класса CvRTrees (классификатор "случайный лес").
- Обучить классификатор.
float Predict(const Ptr<FeatureDetector> keypointsDetector, const Ptr<BOWImgDescriptorExtractor> bowExtractor, const Ptr<CvRTrees> classifier, const string& fileName)
Функция возвращает предсказанную категорию для изображения, хранящегося в файле fileName, и принимает на вход следующие параметры:
- keypointsDetector – детектор ключевых точек;
- bowExtractor – алгоритм, используемый для вычисления признакового описания изображения;
- classifier – обученный классификатор ("случайный лес");
- fileName – входной файл.
Функция должна выполнять следующую последовательность действий:
- Вычислить признаковое описание изображения.
- Предсказать категорию изображения с использованием обученного классификатора и вычисленного признакового описания.
Mat PredictOnTestData(const std::vector<string>& filesList, const std::vector<bool>& isTrain, const Ptr<FeatureDetector> keypointsDetector, const Ptr<BOWImgDescriptorExtractor> bowExtractor, const Ptr<CvRTrees> classifier)
Функция возвращает матрицу, содержащую предсказанные категории для всех объектов из тестовой выборки, и принимает на вход следующие аргументы:
- filesList – список файлов;
- isTrain – маска, описывающая набор изображений из filesList, используемых для обучения классификатора;
- keypointsDetector – детектор ключевых точек;
- bowExtractor – алгоритм, используемый для вычисления признакового описания изображения;
- classifier – обученный классификатор "случайный лес".
Функция должна выполнять следующую последовательность действий:
- Вычислить число изображений в тестовой выборке (оно равно числу элементов в массиве isTrain, значение которых равно false).
- Создать матрицу, используемую для хранения предсказанных категорий изображений: число строк равно числу объектов в тестовой выборке, число столбцов равно 1, элементами матрицы являются 32-битные целые числа со знаком.
- Для каждого изображения из тестовой выборки: предсказать его категорию и скопировать е? значение в соотвествующий элемент матрицы, хранящей предсказанные значения.
Mat GetTestResponses(const Mat& responses, const vector<bool>& isTrain)
Функция возвращает матрицу, содержащую правильные категории (ответы) для изображений из тестовой выборки, и принимает на вход следующие аргументы:
- responses – ответы (категории) для всех изображений;
- isTrain – маска, описывающая набор изображений, использованных для обучения классификатора.
Функция должна выполнять следующую последовательность действий:
- Вычислить число изображений в тестовой выборке (оно равно числу элементов в массиве isTrain, значение которых равно false).
- Создать матрицу, используемую для хранения категорий изображений: число строк равно числу объектов в тестовой выборке, число столбцов равно 1, элементами матрицы являются 32-битные целые числа со знаком.
- Для каждого объекта из тестовой выборки: скопировать категорию данного объекта в соотвествующий элемент матрицы, хранящей парвильные значения категорий объектов из тестовой выборки.
float CalculateMisclassificationError(Mat& responses, Mat& predictions)
Функция возвращает ошибку классификации (доля неправильно предсказанных категорий изображений) и принимает на вход следующие аргументы:
- responses – правильные ответы (категории);
- predictions – предсказанные ответы (категории).
Функция должна выполнять следующую последовательность действий:
- Вычислить число несовпадений соответствующих элементов в массивах responses и predictions.
- Вычислить отношение числа несовпадений к общему числу объектов.
Рассмотрим структуру основной функции приложения:
-
Считать аргументы, переданные программе через командную строку:
- string folder1 – путь к папке, содержащей объекты первой категории;
- string folder2 – путь к папке, содержащей объекты второй категории;
- string detectorType – тип детектора ключевых точек;
- string descriptorType – тип дескрипторов ключевых точек;
- int vocSize – размер словаря;
- double trainProportion – доля объектов, используемых для построения словаря (и обучения классификатора "случайный лес").
- Инициализировать модуль nonfree, обеспечивающий работу с SIFT и SURF детекторами и дескрипторами.
- Создать объект класса, детектирующего ключевые точки (типа detectorType).
- Создать объект класса типа, вычисляющего дескрипторы ключевых точек (типа descriptorType).
- Создать объект класса, предназначенного для нахождения ближайшего к дескриптору "слова" из словаря дескрипторов ключевых точек (типа "BruteForce").
- Создать объект класса, предназначенного для вычисления признакового описания изображений.
- Создать массив, предназначенный для хранения списка, хранящего имена JPEG файлов из folder1 и folder2.
- Заполнить созданный список именами файлов из обеих категорий, вычислить число изображений, относящихся к первой и второй категории, и суммарное число изображений.
- Создать массив для хранения маски, описывающей разбиение изображений на тренировочную и тестовую выборки. Инициализировать его случайными значениями таким образом, чтобы доля объектов, относящихся к тренировочной выборке была равна trainProportion.
- Создать матрицу, содержащую категории изображений: число строк равно суммарному числу изображений, число столбцов равно 1, элементами матрицы являются 32-битные целые числа со знаком. Заполнить матрицу следующим образом: объектам, относящимся к первой категории, соотвествует значение 1, объектам, относящимся ко второй категории – -1.
- Обучить словарь дескрипторов ключевых точек на изображениях, относящихся к тренировочной выборке.
- Установить словарь.
- Сформировать тренировочную выборку для классификатора "случайный лес".
- Обучить классификатор "случайный лес" на сформированной выборке.
- Предсказать категории изображений, относящихся к тестовой выборке.
-
Сформировать матрицу, содержащую правильные категории изображений из тестовой выборки.
Вычислить и вывести ошибку классификации на тестовой выборке.
3.1.3. Параметры запуска приложения
Исходный вычислительный эксперимент необходимо провести со следующими параметрами:
- folder1 – путь к папке crocodile;
- folder2 – путь к папке leopards;
- detectorType – SIFT;
- descriptorType – SIFT;
- vocSize – 25;
- trainProportion – 0.5.