使用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));
}
}
上一篇: C++写取模所存在的问题以及解决的方案
下一篇: 拓扑序列--HDU 2647