用sqlite保存多个人脸特征数据

建立文件夹

face/samplecode/ASFTestDemo/build$ mkdir ../jpg_pre_extra
face/samplecode/ASFTestDemo/build$ mkdir ../jpg_extred
face/samplecode/ASFTestDemo/build$ mkdir ../jpg_err_extred

在int database_init(void)中添加建表程序
表包含几项:
id 整形,主键,自增
feature blob形,用来保存人脸特征数据
name 字符,256长,非空,保存姓名
idcn 字符,18长,非空,唯一,用于保存身份证号

//建表,保存人脸特征数据
    //id int 主键 自增| feature  blob| name varchar(255)|  idcn varchar(18) 唯一
    snprintf(cmd, sizeof(cmd),
             "CREATE TABLE IF NOT EXISTS %s (id INTEGER PRIMARY KEY AUTOINCREMENT, feature blob, name varchar(256) NOT NULL, idcn varchar(18) NOT NULL UNIQUE)",
             DATABASE_TABLE);
    if (sqlite3_exec(g_db, cmd, 0, 0, &err) != SQLITE_OK) {
        sqlite3_close(g_db);
        g_db = NULL;
        printf("%s create table %s failed!\n", __func__, DATABASE_TABLE);
        return -1;
    }

抽取人脸特征的程序

//抽取底库的人脸特征
//int width 输入数据的宽度
//int height 输入数据的高度
//MUInt8* rgb888_data 输入数据
//ASF_FaceFeature *pout_feature 输出特征的地址
int arcsorft_face_process(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 res;
	}

	//照片中存在多个人脸
	else if(detectedFaces.faceNum != 1) {
		printf("faceNum: %d, not 1\n", detectedFaces.faceNum);
		//getchar();
		pthread_mutex_unlock(&g_mutex);
		return -1;
	}

	//单个人脸抽取人脸特征
	else
	{
		SingleDetectedFaces.faceRect.left = detectedFaces.faceRect[0].left;
		SingleDetectedFaces.faceRect.top = detectedFaces.faceRect[0].top;
		SingleDetectedFaces.faceRect.right = detectedFaces.faceRect[0].right;
		SingleDetectedFaces.faceRect.bottom = detectedFaces.faceRect[0].bottom;
		SingleDetectedFaces.faceOrient = detectedFaces.faceOrient[0];

		printf("face num: %d, left: %d, top: %d, right: %d, bottom: %d, faceOrient: %d \n", detectedFaces.faceNum,
			                                                                 detectedFaces.faceRect[0].left,
																			 detectedFaces.faceRect[0].top,
																			 detectedFaces.faceRect[0].right,
																			 detectedFaces.faceRect[0].bottom,
																			 detectedFaces.faceOrient[0]);
			
		// 单人脸特征提取
		res = ASFFaceFeatureExtractEx(handle, &offscreen, &SingleDetectedFaces, pout_feature);
		if (res != MOK)
		{
			printf("ASFFaceFeatureExtractEx fail: %ld\n", res);
		}
		else
		{				
			//printf("featureSize: %d\n", pout_feature->featureSize);    
		}
		pthread_mutex_unlock(&g_mutex);
		return res;
	}
}

插入人脸数据的程序

//人脸特征的增,改
//data feature数据
//size feature数据 长度
int database_insert(void *data, size_t size, const char *name, size_t n_size, const char *idcn, bool sync_flag)
{
    char cmd[256];
    int ret = -1;
    sqlite3_stmt *stat = NULL;

    if (n_size > NAME_LEN) {
        printf("%s n_size error\n", __func__);
        return -1;
    }
    pthread_mutex_lock(&g_mutex);
    //id, feature, name, icdn
    snprintf(cmd, sizeof(cmd), "REPLACE INTO %s (feature, name, idcn) VALUES(?, '%s', '%s');", DATABASE_TABLE_FEATURE, name, idcn);
    printf("%s\n", cmd);
    ret = sqlite3_prepare(g_db, cmd, -1, &stat, 0);
    if (ret != SQLITE_OK) {
        pthread_mutex_unlock(&g_mutex);
        printf("sqlite3_prepare fail \n");
        return ret;
    }

    ret = sqlite3_exec(g_db, "begin transaction", NULL, NULL, NULL);
    if (ret != SQLITE_OK) {
        pthread_mutex_unlock(&g_mutex);
        printf("sqlite3_exec fail \n");
        return ret;
    }

    ret = sqlite3_bind_blob(stat, 1, data, size, NULL);
    if (ret != SQLITE_OK) {
        pthread_mutex_unlock(&g_mutex);
        printf("sqlite3_bind_blob fail \n");
        return ret;
    }
    ret = sqlite3_step(stat);
    if (ret != SQLITE_DONE) {
        pthread_mutex_unlock(&g_mutex);
        printf("sqlite3_step fail \n");
        return ret;
    }
    ret = sqlite3_finalize(stat);
    if (ret != SQLITE_OK) {
        pthread_mutex_unlock(&g_mutex);
        printf("sqlite3_finalize fail \n");
        return ret;
    }

    ret = sqlite3_exec(g_db, "commit transaction", NULL, NULL, NULL);
    if (ret != SQLITE_OK) {
        pthread_mutex_unlock(&g_mutex);
        printf("sqlite3_exec fail \n");
        return ret;
    }

    if (sync_flag) {
        sync();
        //database_bak();
    }
    pthread_mutex_unlock(&g_mutex);

    printf("insert data ok \n");

    return ret;
}

主程序调用

int main()
{
	int ret = -1;
	unsigned char* pjpg_data = NULL;
	unsigned char* pbgr_data = (unsigned char*)malloc(1);
	int width, height;

	//初始化数据库
    ret = database_init();
	if(ret != 0)
	{
		printf("database_init false! \n");
		return -1;
	}
	//读取APPID, SDKKEY

	char* appid = (char*)malloc(1);
	char* sdkkey = (char*)malloc(1);
	int id_size, key_size; 

	get_data_by_name((char*)"text_APPID", NULL, &appid, NULL, NULL, &id_size);
	get_data_by_name((char*)"text_SDKKEY", NULL, &sdkkey, NULL, NULL, &key_size);

	arcsorft_init(appid, sdkkey);

	//读照片

	//等待抽取特征的头像
	const char* jpg_pre_extra_path = "../jpg_pre_extra";

	//已经抽取特征的头像
	const char* jpg_extred_path = "../jpg_extred";

	//有错误的头像
	const char* jpg_err_extred_path = "../jpg_err_extred";
	//打开文件夹
	DIR* dirp = opendir(jpg_pre_extra_path);
	struct dirent* dp;
	//历遍里面每一个文件
	int i = 1;
    while ((dp = readdir(dirp)) != nullptr) {
        if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) {
            char jpg_name[300];	
			char new_name[300] = {0};

			sprintf(jpg_name, "%s/%s", jpg_pre_extra_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_process(width, height, pbgr_data, &feature);
			//有错误的话把图片放到 ../jpg_err_extred 文件夹
			if(ret != 0) {
				//移动文件
				sprintf(new_name, "%s/%s", jpg_err_extred_path, dp->d_name);
				rename(jpg_name, new_name);
				continue;
			} 	

		    char workerName[255] = {0};
		    char idNumber[19] = {0};
		    memcpy(workerName, dp->d_name, 18);
		    memcpy(idNumber, dp->d_name, 18);
		    printf("workerName:%s, idNumber: %s\n", workerName, idNumber);
		   
		    //把人员插入数据库
		    ret = database_insert(feature.feature, feature.featureSize, workerName, 0, idNumber, 1);	

		    if(ret == 0) {
				//移动文件
				//成功的话把文件移到../jpg_extred
				sprintf(new_name, "%s/%s", jpg_extred_path, dp->d_name);
				rename(jpg_name, new_name);
			}
			else {
				//移动文件
				//有错误的话把图片放到 ../jpg_err_extred 文件夹
				sprintf(new_name, "%s/%s", jpg_err_extred_path, dp->d_name);
				rename(jpg_name, new_name);
			}	
        }
		
	}
	//释放内存
	free(pbgr_data);
	//关闭文件夹
    closedir(dirp);
	getchar();
	arcsorft_deinit ();
    return 0;
}

编译运行

在…/jpg_pre_extra 放一张头像
https://gss0.baidu.com/-4o3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/7a899e510fb30f24a62ad935cb95d143ad4b0357.jpg
命名为 200000000000000002.jpg

make 编译后运行

face/samplecode/ASFTestDemo/build$ make
Scanning dependencies of target arcsoft_face_engine_test
[ 20%] Building CXX object CMakeFiles/arcsoft_face_engine_test.dir/samplecode.cpp.o
[ 40%] Linking CXX executable arcsoft_face_engine_test
[100%] Built target arcsoft_face_engine_test

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
pic ../jpg_pre_extra/200000000000000002.jpg width: 392, height: 567
face num: 1, left: 67, top: 107, width: 248, height: 248, faceOrient: 1
workerName:200000000000000002, idNumber: 200000000000000002
REPLACE INTO face_feature (feature, name, idcn) VALUES(?, '200000000000000002', '200000000000000002');
insert data ok

ASFUninitEngine sucess: 0

数据库中可以见到成功插入的项
插入项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值