准备
建立文件夹,把要对比的图片放进去
face/samplecode/ASFTestDemo/build$ mkdir ../jpg_cmp
提取最大那个人脸的特征
int arcsorft_face_process2(int width, int height, MUInt8* rgb888_data, ASF_FaceFeature *pout_feature) {
pthread_mutex_lock(&g_mutex);
MRESULT res = MOK;
ASVLOFFSCREEN offscreen = { 0 };
ColorSpaceConversion(width, height, ASVL_PAF_RGB24_B8G8R8, rgb888_data, offscreen);
ASF_MultiFaceInfo detectedFaces = { 0 };
ASF_SingleFaceInfo SingleDetectedFaces = { 0 };
res = ASFDetectFacesEx(handle, &offscreen, &detectedFaces);
if (res != MOK) {
printf("ASFDetectFaces fail: %ld\n", res);
//getchar();
pthread_mutex_unlock(&g_mutex);
return -1;
}
//没有发现人脸,直接返回0
else if(detectedFaces.faceNum == 0) {
//printf("faceNum: %d, not 1\n", detectedFaces.faceNum);
//getchar();
pthread_mutex_unlock(&g_mutex);
return 0;
}
//发现人脸
else
{
int face_index = 0;
int max_width = 0;
int face_width = 0;
int i = 0;
//多个人脸的话,取他们脸最宽的那个
if(detectedFaces.faceNum > 1) {
for(i = 0; i < detectedFaces.faceNum; i++){
/*
printf("left: %d, top: %d, right: %d, bottom: %d \n",
detectedFaces.faceRect[i].left,
detectedFaces.faceRect[i].top,
detectedFaces.faceRect[i].right,
detectedFaces.faceRect[i].bottom);
*/
face_width = detectedFaces.faceRect[i].right - detectedFaces.faceRect[i].left;
if(face_width > max_width) {
face_index = i;
max_width = face_width;
}
}
}
SingleDetectedFaces.faceRect.left = detectedFaces.faceRect[face_index].left;
SingleDetectedFaces.faceRect.top = detectedFaces.faceRect[face_index].top;
SingleDetectedFaces.faceRect.right = detectedFaces.faceRect[face_index].right;
SingleDetectedFaces.faceRect.bottom = detectedFaces.faceRect[face_index].bottom;
SingleDetectedFaces.faceOrient = detectedFaces.faceOrient[face_index];
// 单人脸特征提取
res = ASFFaceFeatureExtractEx(handle, &offscreen, &SingleDetectedFaces, pout_feature);
if (res != MOK)
{
printf("left: %d, top: %d, right: %d, bottom: %d ASFFaceFeatureExtractEx fail: 0x%lx\n",
SingleDetectedFaces.faceRect.left,
SingleDetectedFaces.faceRect.top,
SingleDetectedFaces.faceRect.right,
SingleDetectedFaces.faceRect.bottom,
res);
pthread_mutex_unlock(&g_mutex);
return -1;
}
pthread_mutex_unlock(&g_mutex);
return 1;
}
pthread_mutex_unlock(&g_mutex);
return 0;
}
人脸对比
//人脸特征对比
float arcsorft_face_comp(LPASF_FaceFeature pfeature1,LPASF_FaceFeature pfeature2) {
MRESULT res = MOK;
MFloat confidenceLevel;
pthread_mutex_lock(&g_mutex);
res = ASFFaceFeatureCompare(handle, pfeature1, pfeature2, &confidenceLevel);
pthread_mutex_unlock(&g_mutex);
return confidenceLevel;
}
建立所有人脸数据内存
建立一个内存区域,里面能保存3000个人脸特征,名字,身份证号。
#define face_table_len 3000*(1032+255+19)
static unsigned char face_table[face_table_len] = {0};
static int face_count = 0;
数据库中所有的人脸特征
//get数据库的数据 SELECT * FROM face_data
//用于更新整个人脸数据表
//人脸数据为unsigned char[1032](blod 人脸特征数据)+char[255](名字)+char[19](身份证号) *3000
int database_get_data(void *dst, const int cnt)
{
int ret = 0;
char cmd[256];
sqlite3_stmt *stat = NULL;
int index = 0;
const void *data;
size_t size;
pthread_mutex_lock(&g_mutex);
snprintf(cmd, sizeof(cmd), "SELECT * FROM %s;", DATABASE_TABLE_FEATURE);
if (sqlite3_prepare(g_db, cmd, -1, &stat, 0) != SQLITE_OK) {
pthread_mutex_unlock(&g_mutex);
return 0;
}
while (1) {
ret = sqlite3_step(stat);
if (ret != SQLITE_ROW)
break;
//人脸特征数据
data = sqlite3_column_blob(stat, 1);
size = sqlite3_column_bytes(stat, 1);
//复制到表中
memcpy((unsigned char*)dst, data, size);
dst += 1032;
//名字
data = sqlite3_column_text(stat, 2);
size = sqlite3_column_bytes(stat, 2);
//复制到表中
memcpy((unsigned char*)dst, data, size);
dst += 255;
//身份证号
data = sqlite3_column_text(stat, 3);
size = sqlite3_column_bytes(stat, 3);
//复制到表中
memcpy((unsigned char*)dst, data, size);
dst += 19;
if (++index >= cnt)
break;
}
sqlite3_finalize(stat);
pthread_mutex_unlock(&g_mutex);
return index;
}
主程序从数据库中读取到人脸的信息,放内存中,
//清内存
memset(face_table, 0, face_table_len);
//更新整个人脸数据表
face_count = 0;
face_count = database_get_data((unsigned char*)face_table, 3000);
读取文件夹里面的人脸,抽取人脸特征,和内存中的人脸数据进行比对
//文件夹
const char* jpg_cmp_path = "../jpg_cmp";
//打开文件夹
dirp = opendir(jpg_cmp_path);
while ((dp = readdir(dirp)) != nullptr) {
if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) {
char jpg_name[300];
sprintf(jpg_name, "%s/%s", jpg_cmp_path, dp->d_name);
//打开文件
FILE* fpjpg = fopen(jpg_name, "rb");
//查文件的长度
fseek(fpjpg, 0, SEEK_END);
long file_length = ftell(fpjpg);
fseek(fpjpg, 0, SEEK_SET);
//分配内存
pjpg_data = (unsigned char*)malloc(file_length);
//读取数据
fread(pjpg_data, 1, file_length, fpjpg); //jpeg文件数据
//关闭文件
fclose(fpjpg);
//把jpg图片解码成bgr数据
jpg2bgr(pjpg_data, file_length, &pbgr_data, &width, &height);
printf("pic %s width: %d, height: %d \n", jpg_name, width, height);
//抽取人脸特征
ASF_FaceFeature feature;
ret = arcsorft_face_process2(width, height, pbgr_data, &feature);
//如果发现了人脸, 人脸对比
if(ret == 1){
//人脸对比
ASF_FaceFeature feature1;
float confidenceLevel = 0.0;
float max_confidenceLevel = 0.0;
int max_similar_id = -1;
for(int i = 0; i < face_count; i++) {
feature1.feature = face_table + i * (1032 + 255 + 19);
feature1.featureSize = 1032;
//printf("%s\n", face_table + i * (1032 + 255 + 19) + 1032);
confidenceLevel = arcsorft_face_comp(&feature1,&feature);
//置信度大于阈值, 并且阈值大于以前的
if(confidenceLevel > 0.8 && confidenceLevel > max_confidenceLevel) {
max_confidenceLevel = confidenceLevel;
max_similar_id = i;
}
}
//max_similar_id
if(max_similar_id != -1){
printf("%s is name: %s, id: %s, max_confidenceLevel: %f\n", dp->d_name,
&face_table[max_similar_id*(1032 + 255 + 19) +1032],
&face_table[max_similar_id*(1032 + 255 + 19) +1032 + 255],
max_confidenceLevel);
//sleep(5);
}
else{
printf("not white table person!!!!!!!!!!!\n");
}
max_similar_id = -1;
} else {
printf("process2 err \n");
continue;
}
}
}
//释放内存
free(pbgr_data);
//关闭文件夹
closedir(dirp);
编译运行测试
编译运行结果
face/samplecode/ASFTestDemo/build$ ./arcsoft_face_engine_test
************* ArcFace SDK Info *****************
startTime: 2024-09-09 00:00:00
endTime: 2025-09-09 00:00:00
Version:3.0.12402010101.3
BuildDate:07/29/2020
CopyRight:Copyright 2020 ArcSoft Corporation Limited. All rights reserved.
************* Face Recognition *****************
ASFInitEngine sucess: 0
face_count: 2322
pic ../jpg_cmp/111.jpg width: 640, height: 807
111.jpg is name: 200000000000000001, id: 200000000000000001, max_confidenceLevel: 0.962285
pic ../jpg_cmp/200000000000000001.jpg width: 376, height: 390
200000000000000001.jpg is name: 200000000000000001, id: 200000000000000001, max_confidenceLevel: 1.000000
pic ../jpg_cmp/ffff.jpg width: 1280, height: 1280
ffff.jpg is name: 100000000000000552, id: 100000000000000552, max_confidenceLevel: 0.989109
pic ../jpg_cmp/222.jpg width: 636, height: 609
not white table person!!!!!!!!!!!
pic ../jpg_cmp/333.jpg width: 492, height: 473
333.jpg is name: 200000000000000001, id: 200000000000000001, max_confidenceLevel: 0.917396
ASFUninitEngine sucess: 0