使用Eigen庫加速人臉搜索

速度提升:200維特徵值在1w底庫上的搜索時間,從16ms左右,下降到2ms左右。

提升方法:

       抓拍人臉到底庫做搜索,大部分時間消耗在抓拍圖和底庫每個人臉向量計算歐式距離,並排序的過程中。

原匹配算法:

void faceMatch(std::vector<std::vector<float>> face_feature, std::vector<std::vector<float>> temp_feature, std::vector<std::string> temp_id, std::vector<std::vector<std::string>>& match_result)
{
	int num = temp_feature.size();					// 註冊人臉數量
	std::vector<float> tmp_feature;					// 臨時人臉特徵
	
	clock_t start, end;
	for (int k = 0; k < face_feature.size(); k++)
	{
		start = clock();
		tmp_feature = face_feature[k];				// 1*512
		
		std::vector<float> dist;
		for (int i = 0; i < num; i++)				// 當前人臉與特徵庫人臉進行比對
		{
			//// 作差
			std::vector<float> subs;
			std::transform(tmp_feature.begin(), tmp_feature.end(), temp_feature[i].begin(), std::back_inserter(subs), [&](float l, float r)
			{
				//return std::abs(l - r);
				return (l - r);
			});
			// 取平方並求和
			float tmp_dist = 0.0f;
			for (auto it : subs)
			{
				it = it * it;
				tmp_dist += it;
			}
			dist.push_back(tmp_dist);
			
		}
		// 求最小距離所在行
		auto smallest = std::min_element(std::begin(dist), std::end(dist));
		int index = std::distance(std::begin(dist), smallest);		// 最小變量所在行
		match_result[k].push_back(temp_id[index]);					// 保存id名稱
	    // 求相似度-點乘
		std::vector<float> multi;
		std::transform(tmp_feature.begin(), tmp_feature.end(), temp_feature[index].begin(), std::back_inserter(multi), [&](float l, float r)
		{
			//return std::abs(l * r);
			return (l * r);
		});
		// 求相似度-Σsim
		float simi = 0.0f;
		for (auto i : multi)
		{
			simi += i;
		}
		end = clock();
		// 保存simi
		match_result[k].push_back(std::to_string(simi));
		// 保存比對時間
		//match_result[k].push_back(std::to_string(end - start));
		match_result[k].push_back(std::to_string(end - start));
	}
}

優化後的代碼:

#include <Eigen/Dense>
typedef Eigen::Matrix<float, 1, PCA_DIMS, Eigen::RowMajor> FEATURE;

void fea2FEATURE(std::vector<float> fea, FEATURE &feature)
{
	for (int i = 0; i < fea.size(); ++i)
		feature[i] = fea[i];
}

void faceMatch(std::vector<std::vector<float>> face_feature, std::vector<std::vector<float>> temp_feature, std::vector<std::string> temp_id, std::vector<std::vector<std::string>>& match_result)
{
	int num = temp_feature.size();					// 註冊人臉數量
	std::vector<float> tmp_feature;					// 臨時人臉特徵
	
	clock_t start, end;
	for (int k = 0; k < face_feature.size(); k++)
	{
		start = clock();
		tmp_feature = face_feature[k];				// 1*512
		
		FEATURE tmpfea;
		fea2FEATURE(tmp_feature, tmpfea);

		std::vector<float> dist;
		for (int i = 0; i < num; i++)				// 當前人臉與特徵庫人臉進行比對
		{
			// 
			FEATURE tempfea;
			fea2FEATURE(temp_feature[i], tempfea);
			float tmpdist = (tmpfea - tempfea).norm();
			dist.push_back(tmpdist);

			//// 作差
			//std::vector<float> subs;
			//std::transform(tmp_feature.begin(), tmp_feature.end(), temp_feature[i].begin(), std::back_inserter(subs), [&](float l, float r)
			//{
			//	//return std::abs(l - r);
			//	return (l - r);
			//});
			//// 取平方並求和
			//float tmp_dist = 0.0f;
			//for (auto it : subs)
			//{
			//	it = it * it;
			//	tmp_dist += it;
			//}
			//dist.push_back(tmp_dist);
			
		}
		// 求最小距離所在行
		auto smallest = std::min_element(std::begin(dist), std::end(dist));
		int index = std::distance(std::begin(dist), smallest);		// 最小變量所在行
		match_result[k].push_back(temp_id[index]);					// 保存id名稱
	    // 求相似度-點乘
		std::vector<float> multi;
		std::transform(tmp_feature.begin(), tmp_feature.end(), temp_feature[index].begin(), std::back_inserter(multi), [&](float l, float r)
		{
			//return std::abs(l * r);
			return (l * r);
		});
		// 求相似度-Σsim
		float simi = 0.0f;
		for (auto i : multi)
		{
			simi += i;
		}
		end = clock();
		// 保存simi
		match_result[k].push_back(std::to_string(simi));
		// 保存比對時間
		//match_result[k].push_back(std::to_string(end - start));
		match_result[k].push_back(std::to_string(end - start));
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章