欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用Eigen库加速人脸搜索

程序员文章站 2022-05-21 08:19:11
...

速度提升: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));
	}
}

 

相关标签: 算法学习 算法