Обучите машину опорных векторов распознавать черты лица на C ++
Давайте посмотрим, как обучить модель машины опорных векторов, сохранить обученную модель и протестировать модель, чтобы проверить процент точности ее предсказания с помощью OpenCV.
Организация данных:
Используя imagenetscraper и autocrop, мы собираем данные из Интернета, imagenetscraper
autocrop
Собранные данные должны быть осмысленно организованы, чтобы мы могли получить к ним программный и ручной доступ. Используйте приведенную ниже структуру папок -
FFR_dataset / | - Возраст | | - взрослый | | - ребенок | | - старый | | - подросток | - Эмоции | | - гнев | | - презрение | | - счастлив | | - нейтральный | | - грустно | | - сюрприз | - Пол | - женский | - самец
Мы используем одни и те же имена каталогов в коде для доступа к ним для обучения , сохранения и прогнозирования результатов распознавания. Для обучения моделей и получения хороших результатов прогнозирования требуется минимум 50 изображений в каждой папке. Обучение большего количества изображений может улучшить результаты, но не рекомендуется, так как это занимает много времени и не дает значительных улучшений.
Выполнение
Используя образец, предоставленный в официальном репозитории opencv для обучения SVM с помощью HOG, train_HOG.cpp, мы реализуем код C ++ для обучения, сохранения и прогнозирования черт лица на изображении с несколькими лицами.
Есть три типа функций: возраст , эмоции и пол . Четыре возрастных группы, шесть эмоций и два гендерных типа. Следовательно, реализован n- классификатор для распознавания каждой особенности в данных лица.
Шаг №1: Для каждого типа функции, т. Е. (Возраст, Эмоции или Пол) прокрутите "n" времен выполнения.
// CTrainTestHOG::Run(int run_times) for ( auto ft : m_FeatureList) { DEBUGLW( " Feature type=[%s]
" , ft.first.c_str()); std::vector< float > predictionAccuracyList; predictionAccuracyList.reserve(run_times); for ( int run = 0; run < run_times; ++run) { DEBUGLW( " Run=[%d]
" , run); vector<Mat> trainData, predData; vector< int > trainLabels, predLabels; this ->get_ft_dataset(ft.first, trainData, predData, trainLabels, predLabels); // ... train, predict and measure the SVM model. } } |
Шаг № 2: В каждом прогоне перебирайте значения признаков в типе признаков и получайте изображения в вектор или массив, т.е. получите все изображения из папок Gender-> Male и Gender-> Female.
// CTrainTestHOG::get_ft_dataset() std::set<cv::String>& featureValueList = m_FeatureList.find(ft)->second; for ( auto fv : featureValueList) { DEBUGLW( " Feature value=[%s]
" , fv.c_str()); std::vector<cv::Mat> _trainData; std::vector<cv::Mat> _predData; std::vector< int > _trainLabels; std::vector< int > _predLabels; errCode = this ->get_ftfv_dataset(ft, fv, _trainData, _predData, _trainLabels, _predLabels); if (errCode != EXIT_SUCCESS) break ; trainData.insert(trainData.end(), _trainData.begin(), _trainData.end()); predData.insert(predData.end(), _predData.begin(), _predData.end()); trainLabels.insert(trainLabels.end(), _trainLabels.begin(), _trainLabels.end()); predLabels.insert(predLabels.end(), _predLabels.begin(), _predLabels.end()); } |
Шаги с 3 по 6:
- Обрежьте изображения в векторе до прямоугольников лиц и обновите вектор изображений, добавив в него список новых лиц.
- Выполните любые задачи предварительной обработки, такие как изменение размера до меньшего размера (64, 64) для каждого изображения в списке лиц.
- Перемешайте предварительно обработанные изображения лиц в векторе случайным образом, чтобы ввести случайные входные данные.
- Разделите набор данных на обучающие (80%) и прогнозные (20%) данные.
// CTrainTestHOG::get_ftfv_dataset() std::vector<cv::Mat> imgList; this ->get_images(folderName, imgList); this ->get_cropped_faces(imgList); this ->get_preprocessed_faces(imgList); //-- return on empty img list to prevent seg fault if (imgList.empty()) { errCode = EXIT_FAILURE; DEBUGLE( "Error img list is empty!
" ); break ; } DEBUGLD( " imgList.size()=[%ld]
" , imgList.size()); std::random_shuffle(imgList.begin(), imgList.end()); // 80% for training int trainPart = imgList.size() * 0.8; // 20% for predicting int predPart = imgList.size() - trainPart; DEBUGLD( " trainPart=[%d], predPart=[%d]
" , trainPart, predPart); trainData.reserve(trainPart); predData.reserve(predPart); ft_t::iterator ft_iter = m_FeatureList.find(ft); fv_t::iterator fv_iter = ft_iter->second.find(fv); int label = std::distance(ft_iter->second.begin(), fv_iter); DEBUGLD( " label=[%d]
" , label); int i = 0; for (; i < trainPart; ++i) { trainData.push_back(imgList.at(i)); trainLabels.push_back(label); } DEBUGLD(" i=[%d], trainData.size()=[%ld], trainLabels.size() = [% ld]
", i, trainData.size(), trainLabels.size()); for (; i < imgList.size(); ++i) { predData.push_back(imgList.at(i)); predLabels.push_back(label); } DEBUGLD(" i=[%d], predData.size()=[%ld], predLabels.size() = [% ld]
", i, predData.size(), predLabels.size()); |
Шаг № 7: Вычислить HOG для каждого изображения в обучающих данных.
// CTrainTestHOG::computeHOGs() HOGDescriptor hog; vector<Mat> hogMats; vector< float > descriptors; for ( auto img : imgHogList) { hog.winSize = img.size() / 8 * 8; hog.compute(img, descriptors); cv::Mat descriptors_mat(Mat(descriptors).clone()); hogMats.push_back(descriptors_mat); } imgHogList.swap(hogMats); |
Шаг № 8: Преобразуйте вектор обучающих данных в объект OpenCV Mat для обучения SVM.
// CTrainTestHOG::convert_to_ml() for ( size_t i = 0; i < train_samples.size(); ++i) { CV_Assert(train_samples[i].cols == 1 || train_samples[i].rows == 1); if (train_samples[i].cols == 1) { cv::transpose(train_samples[i], tmp); tmp.copyTo(trainData.row(( int )i)); } else if (train_samples[i].rows == 1) { train_samples[i].copyTo(trainData.row(( int )i)); } } |
Шаг № 9: Передайте объект Mat обучающих данных в функцию svm train вместе с вектором меток для обучающих данных.
// CTrainTestHOG::Run() trainLabels.resize(ml_train_data.rows); // train svm DEBUGLW( " Training SVM - begin
" ); m_pSVM->train(ml_train_data, ROW_SAMPLE, trainLabels); DEBUGLW( " Training SVM - end
" ); |
Шаг № 10: Сохраните обученную модель.
//-- step 10, CTrainTestHOG::Run() cv::String svmModelFileName = cv::format( "%s/cv4_svm_%s_model.xml" , getenv (FFR_DATASET_PATH), ft.first.c_str()); m_pSVM->save(svmModelFileName.c_str()); DEBUGLW( " Saved SVM model=[%s]
" , svmModelFileName.c_str()); |
Шаг № 11: Прогнозируйте модель, вычисляя HOG для каждого изображения прогноза, преобразуйте набор данных прогноза в объект mat opencv и вызовите svm predic с вектором меток для сохранения результата.
//-- step 11, CTrainTestHOG::Run() // test the model // compute HOG for each pre-processed face errCode = this ->computeHOGs(predData); if (errCode != EXIT_SUCCESS) { DEBUGLE( "Error in computing HOGs for the feature " "type=[%s]
" , ft.first.c_str()); break ; } // convert HOG feature vectors to SVM data Mat ml_pred_data; vector< int > resultLabels; errCode = this ->convert_to_ml(predData, ml_pred_data); if (errCode != EXIT_SUCCESS) { DEBUGLE( "Error in converting to ml for the " "feature type=[%s]
" , ft.first.c_str()); break ; } predLabels.resize(ml_pred_data.rows); // resultLabels.resize(ml_pred_data.rows); // test svm DEBUGLW( " Testing SVM - begin
" ); Mat responses_mat; m_pSVM->predict(ml_pred_data, responses_mat); for ( size_t i = 0; i < ml_pred_data.rows; ++i) { resultLabels.push_back(responses_mat.at< int >(i)); } DEBUGLW( " Testing SVM - end
" ); |
Шаг № 12 и № 13: Рассчитайте процент его точности, сравнивая ожидаемые метки предсказания с предсказанными метками.
// CTrainTestHOG::Run() // check the accuracy float accuracy = 0.0f; this ->get_prediction_accuracy(predLabels, resultLabels, accuracy); DEBUGLW( " Prediction accuracy=[%lf]
" , accuracy); predictionAccuracyList.push_back(accuracy); //-- step 13, CTrainTestHOG::Run() // check the mean accuracy of 'n' runs float sum_of_accuracies = std::accumulate( predictionAccuracyList.begin(), predictionAccuracyList.end(), 0.0); float mean_accuracy = sum_of_accuracies / predictionAccuracyList.size(); DEBUGLW( " Mean prediction accuracy=[%lf]
" , mean_accuracy); |
Запустите исполняемый файл с указанными ниже аргументами командной строки.
./train_hog --test --in =--out = --показывать
Вход:
Выход:
Журнал результатов для HOG SVM с использованием OpenCV 2.4
Журнал результатов для HOG SVM с использованием OpenCV 4.0
Примечание. Из-за длинных волос у всех трех человек на изображении пол определяется как «женский», что является ложным срабатыванием. В алгоритмах машинного обучения ложные срабатывания всегда являются обычным явлением, поскольку входной образец изображения имеет неоднозначные характеристики.