Обучите машину опорных векторов распознавать черты лица на 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 faultif (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 trainingint trainPart = imgList.size() * 0.8; // 20% for predictingint 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 svmDEBUGLW( " 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 faceerrCode = 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 dataMat 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 svmDEBUGLW(" 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 accuracyfloat 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' runsfloat 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
Примечание. Из-за длинных волос у всех трех человек на изображении пол определяется как «женский», что является ложным срабатыванием. В алгоритмах машинного обучения ложные срабатывания всегда являются обычным явлением, поскольку входной образец изображения имеет неоднозначные характеристики.