irpas技术客

人脸识别-人脸建库学习:Sqlite3 的基本使用_CodeAIF_人脸识别底库

大大的周 1273

一.创建和调用: face_feature.db 1.测试参考和配置

??????? 参考工程:https://github.com/Qengineering/Face-Recognition-Jetson-Nano

??????? 人脸识别建库需要调用其中:人脸检测(TRetina.cpp)+人脸对齐(TWarp.cpp)+人脸特征(

TArcface.cpp)。

??????? 调试:本次为方便调试,未使用参考工程中cmakelist搭建,选择qt5搭建测试工程,工程qmake.pro 配置:

QT -= gui CONFIG += c++11 console CONFIG -= app_bundle LIBS +=-lpthread \ -fopenmp # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #add opencv INCLUDEPATH += /usr/local/include/opencv \ $$PWD/Include/ncnn/ LIBS += /usr/local/lib/libopencv_* SOURCES += \ src/main_sqlit3.cpp \ Common/cJSON.cpp \ src/TRetina.cpp \ src/TArcface.cpp \ src/TWarp.cpp \ HEADERS += \ Common/cJSON.h \ Common/CppSQLite3.h \ Common/inifile.h \ Common/jsonp.h \ Common/sqlite3.h \ $$PWD/Include/featuredb.h \ $$PWD/Include/TRetina.h \ $$PWD/Include/TArcface.h \ $$PWD/Include/TWarp.h \ #LIBS += -L$$PWD/lib/sqlite -llualibsqlite.0 LIBS += $$PWD/lib/sqlite/libsqlite3.so \ /home/xxx/sqlitefacedb/lib/libncnn.a \ # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target 2.建库目标:

db 文件存储人脸模型输出的1x128维度特征;能够支持戴口罩、不带口罩;

db 数据table 类型如:

nameintNOMASKFEATUREMASKFEATUREXXX_00121X1281X128XXX_00121X1281X128
3.建库需要的工程搭建:

? 基于参考工程调用人脸检测+对其+特征提取:

TWarp Warp; //调用对其 std::vector<FaceObject> Faces; //人脸检测数据结构 const int RetinaWidth = 320; const int RetinaHeight = 240; std::shared_ptr<TRetina> Rn(new TRetina(RetinaWidth, RetinaHeight, false)); //使用智能指针初始化和调用人脸检测 std::shared_ptr<TArcFace> ArcFace(new TArcFace());//使用智能指针初始化和调用人脸特征提取 3.Sqlite3 建立人脸库的基本使用

3.1 创建人脸数据库:

//人脸特征建库前数据存储形式,以下仅参考,对于db文件table 表中的name 和blob 输入可多中方式,如json 也可 std::vector< std::pair<std::string, cv::Mat> > fcdata ; //这里用vector+:pair的形式存储模型输出后names 和人脸的1x128维度的特征; //如果存储一个人多个人脸可用: std::vector< std::pair<std::string, vector<cv::Mat>> > mutilfcdata;

? 以文件夹下img/***1.jpg

??????????????????????? img/***2.jpg 为例,遍历文件下所有图片使用检测+对其+特征提取fc,push进vector便于后续导入db 的table(这种方式,后续需要优化,大数据量情况不合理 )。

//创建脸部特征数据库 int getallimgfeature(string &image_dir,std::vector< std::pair<std::string, cv::Mat> > &tests) { //获取图片数据 vector<cv::String> NameFaces; cv::glob(image_dir, NameFaces); int FaceCnt=NameFaces.size(); if(FaceCnt==0) { cout << "No image files[jpg] in database" << endl; return -1; } for(int i=0; i<FaceCnt; i++){ string temp=NameFaces[i]; std::vector<std::string> tempstring=split(temp, "/"); std::vector<std::string> tempstring2=split(tempstring[tempstring.size()-1], "."); Faces.clear(); cv::Mat imgs=cv::imread(temp,1); cv::Mat result_cnn; cv::resize(imgs, result_cnn, cv::Size(RetinaWidth,RetinaHeight),cv::INTER_LINEAR); Rn->detect_retinaface(result_cnn,Faces); if(Faces[0].FaceProb>0.5){ //get centre aligned image cv::Mat face_schipss = Warp.Process(result_cnn,Faces[0]); Faces[0].align_max=face_schipss; } else{ cout<<"---std--create fail--:"<<endl; return -1; } cv::Mat prob_fc = ArcFace->GetFeature(Faces[0].align_max); //得到人脸特征,这里仅做测试,没有去求真实的最大人脸 cv::Mat prob; normalize(prob_fc,prob,1,0,CV_MINMAX); //opencv 接口归一化 string names=tempstring2[0]; cout<<tempstring2[0]<<endl; tests.push_back(std::make_pair(names, prob)); std::cout<<"-----fc---:"<<prob<<std::endl; } printf("tests: %d\n", tests.size()); }

3.2 Sqlite3 db 创建

??????? 当我们已获取文件夹下图像的id_names和特征后就可以使用sqlite3相关接口创建人脸数据库了,首先要建立db问价和建立table:

sqlite3 *db; char *zErrMsg = 0; int rc; char *sql; sqlite3_stmt* stmt; //打开数据库文件 rc = sqlite3_open("face_feature.db", &db); if( rc ){ fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); exit(0); }else{ fprintf(stdout, "Opened database successfully\n"); } //创建脸部特征表 sql = "CREATE TABLE FEATURES(" \ "NAME VARCHAR(256) NOT NULL," \ "NUMFEA INT NOT NULL," \ "NOMASKFACE BLOB NOT NULL," \ "MASKFACE BLOB NOT NULL);"; rc = sqlite3_exec(db, sql, NULL, 0, &zErrMsg); if( rc != SQLITE_OK ){ fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); }else{ fprintf(stdout, "Table created successfully\n"); }

??????? 当数据表建立后,我们就需要考虑按照自己table 格式导入我们用 std::vector< std::pair<std::string, ncnn::Mat> > facedata数据结构村的数据了。db table 导入的相关语法如下:

//导入前的准备语句 sqlite3_prepare(db,"INSERT INTO FEATURES (NAME,NUMFEA,NOMASKFACE,MASKFACE) VALUES(?,?,?,?);",-1,&stmt,NULL); // 导入 //导入已存结构中的id 名字 在tabel 列中 sqlite3_bind_text(stmt,1,entry[i].first.c_str(),-1,SQLITE_STATIC); //导入已存结构中有几组特征 在tabel 列中 int ,这里只是作为后续扩展一个人脸多个底库特征类型的记录 sqlite3_bind_int(stmt,2,entry[i].second.size[1]); //导入已存结构中的1x128 cv:Mat 特征 在tabel 列中NOMASKFACE--BLOB中 sqlite3_bind_blob(stmt,3,entry[i].second.data,entry[i].second.size[0]*entry[i].second.size[1]*4,SQLITE_TRANSIENT); //导入已存结构中的1x128 cv:Mat 特征 在tabel 列中MASKFACE--BLOB中 sqlite3_bind_blob(stmt,4,entry[0].second.data,entry[i].second.size[0]*entry[i].second.size[1]*4,SQLITE_TRANSIENT); rc = sqlite3_step(stmt);

3.2 Sqlite3 db 生成后调用

??????? 当建立face_feature.db后,对于人脸识别系统来说,我们需要遍历db数据table中存储的人脸特征与输入人脸特征做1:N比较,并返回最大pred 得分和对应id name

.... 梳理测中。。。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #人脸识别底库 #1 #基于U官方版本代码训练 #2 #修改rknn #17