139 lines
4.9 KiB
C++
139 lines
4.9 KiB
C++
|
|
//
|
|||
|
|
// created by wangjiale on 2024/5/9
|
|||
|
|
// description: 对face_folder中的人脸计算sim,然后将sim储存在txt文件中,然后用python 处理这些sim得到AUC曲线并得到合适的阈值。
|
|||
|
|
#include "lite/lite.h"
|
|||
|
|
#include <fstream>
|
|||
|
|
#include <iostream>
|
|||
|
|
#include "dirent.h"
|
|||
|
|
#include <sys/stat.h>
|
|||
|
|
#include <random>
|
|||
|
|
|
|||
|
|
|
|||
|
|
struct Node{
|
|||
|
|
std::string name;
|
|||
|
|
std::vector<std::vector<float>> embeddings;
|
|||
|
|
int num_embd;
|
|||
|
|
Node() :num_embd(0){};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
int main(int argc, char* argv[]){
|
|||
|
|
|
|||
|
|
const std::string detect_onnx = R"(C:\Users\JIALE\Desktop\bns_proj\test2_ort\pipeline\hub\Pytorch_RetinaFace_resnet50.onnx)";
|
|||
|
|
const std::string reg_onnx = R"(C:\Users\JIALE\Desktop\bns_proj\test2_ort\pipeline\hub\focal-arcface-bh-ir50-asia.onnx)";
|
|||
|
|
if (argc <= 1)
|
|||
|
|
{
|
|||
|
|
std::cerr << "argc <= 1" <<std::endl;
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
std::string face_folder = argv[1]; //R"(path/to/face_folder)";
|
|||
|
|
|
|||
|
|
lite::cv::face::detect::RetinaFace *retinaface = new lite::cv::face::detect::RetinaFace(detect_onnx); //default: Pytorch_RetinaFace_resnet50.onnx
|
|||
|
|
lite::cv::faceid::FocalAsiaArcFace *focal_asia_arcface = new lite::cv::faceid::FocalAsiaArcFace(reg_onnx); //default: focal-arcface-bh-ir50-asia.onnx
|
|||
|
|
|
|||
|
|
std::vector<Node> nodes; //储存着人脸的内容
|
|||
|
|
|
|||
|
|
// get face embeddings from folder
|
|||
|
|
if (face_folder.back() != '/' || face_folder.back() != '\\')
|
|||
|
|
face_folder.push_back('/');
|
|||
|
|
DIR* dir = opendir(face_folder.c_str());
|
|||
|
|
if (dir == nullptr){
|
|||
|
|
std::cerr << "Cannot open directory: " << face_folder << std::endl;
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
struct dirent *outEntry, *entry;
|
|||
|
|
while((outEntry=readdir(dir)) != nullptr)
|
|||
|
|
{
|
|||
|
|
std::string foldername = outEntry->d_name;
|
|||
|
|
if(foldername.find('.') != std::string::npos)
|
|||
|
|
continue;
|
|||
|
|
std::string subfolder = face_folder + foldername + '/';
|
|||
|
|
DIR* subdir = opendir(subfolder.c_str());
|
|||
|
|
|
|||
|
|
Node node;
|
|||
|
|
while ((entry = readdir(subdir)) != nullptr)
|
|||
|
|
{
|
|||
|
|
std::string fileName = entry->d_name;
|
|||
|
|
if(fileName == "." || fileName ==".." || fileName.find(".jpg") == std::string::npos)
|
|||
|
|
continue;
|
|||
|
|
std::string filePath = subfolder + fileName;
|
|||
|
|
|
|||
|
|
cv::Mat img_bgr = cv::imread(filePath);
|
|||
|
|
lite::types::FaceContent known_face_content;
|
|||
|
|
std::vector<lite::types::Boxf> detected_boxes;
|
|||
|
|
retinaface->detect(img_bgr, detected_boxes);
|
|||
|
|
if (detected_boxes.empty() || detected_boxes.size() > 1 || !detected_boxes[0].flag )
|
|||
|
|
{
|
|||
|
|
std::cout << filePath + ": has " + std::to_string(static_cast<int>(detected_boxes.size()));
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
focal_asia_arcface->detect(img_bgr(detected_boxes[0].rect()), known_face_content);
|
|||
|
|
if (known_face_content.flag){
|
|||
|
|
node.embeddings.push_back(known_face_content.embedding);
|
|||
|
|
++ node.num_embd;
|
|||
|
|
// node.name = fileName.substr(0,fileName.size()-4);
|
|||
|
|
}
|
|||
|
|
// std::cout << "File name: " << fileName << std::endl;
|
|||
|
|
// std::cout << "File path: " << filePath << std::endl;
|
|||
|
|
}
|
|||
|
|
node.name = foldername;
|
|||
|
|
nodes.push_back(node);
|
|||
|
|
closedir(subdir);
|
|||
|
|
}
|
|||
|
|
closedir(dir);
|
|||
|
|
|
|||
|
|
// compute sim between faces
|
|||
|
|
vector<int> flags;
|
|||
|
|
vector<float> sims;
|
|||
|
|
std::random_device rd;
|
|||
|
|
std::mt19937 gen(rd());
|
|||
|
|
int num_sel = 8;
|
|||
|
|
for(int i = 0; i < nodes.size(); i++ )
|
|||
|
|
{
|
|||
|
|
//compute negative similarity
|
|||
|
|
std::vector<float>& source_embedding = nodes[i].embeddings[0];
|
|||
|
|
for(int j = 0; j < num_sel; j++ )
|
|||
|
|
{
|
|||
|
|
int idx = i;
|
|||
|
|
while(idx == i)
|
|||
|
|
idx = std::uniform_int_distribution<int>(0,nodes.size()-1)(gen);
|
|||
|
|
int iidx = std::uniform_int_distribution<int>(0,nodes[idx].num_embd)(gen);
|
|||
|
|
std::vector<float>& target_embedding = nodes[idx].embeddings[iidx];
|
|||
|
|
flags.push_back(0);
|
|||
|
|
sims.push_back(
|
|||
|
|
lite::utils::math::cosine_similarity<float>(source_embedding, target_embedding)
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//compute positive similarity
|
|||
|
|
vector<vector<float>& embds = nodes[i].embeddings;
|
|||
|
|
for(int a = 0; a < embds.size(); a++)
|
|||
|
|
{
|
|||
|
|
for(int b = a+1; b < embds.size(); b++)
|
|||
|
|
{
|
|||
|
|
flags.push_back(1);
|
|||
|
|
sims.push_back(
|
|||
|
|
lite::utils::math::cosine_similarity<float>(
|
|||
|
|
embds[a], embds[b])
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
delete retinaface;
|
|||
|
|
delete focal_asia_arcface;
|
|||
|
|
|
|||
|
|
std::ofstream simfile("simfile.txt");
|
|||
|
|
std::ofstream intfile("intfile.txt");
|
|||
|
|
for(float similarity : sims)
|
|||
|
|
simfile << static_cast<float>(similarity) << std::endl;
|
|||
|
|
for(int flag : flags)
|
|||
|
|
intfile << static_cast<int>(flag) << std::endl;
|
|||
|
|
|
|||
|
|
simfile.close();
|
|||
|
|
intfile.close();
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|