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