0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【EASY EAI Nano开源套件试用体验】5AI功能测试之多人脸识别

开发板试用精选 来源:开发板试用 作者:电子发烧友论坛 2022-10-11 16:33 次阅读

本文来源电子发烧友社区,作者:码农爱学习, 帖子地址:https://bbs.elecfans.com/jishu_2308719_1_1.html



上篇文章,测试了EASY EAI Nano的人脸检测功能,本篇进行人脸识别功能。

人脸检测,只是将图像中的人脸的位置检测出来,人脸识别,又增加了一部,在检测到人脸后,还要识别出这张脸是谁的脸。

本篇参考官方文档:https://www.easy-eai.com/document_details/3/110
1.png

1 API介绍

组件 头文件以及库路径 描述
系统操作组件 easyeai-api/common_api/system_opt 提供线程操作函数
摄像头组件 easyeai-api/peripheral_api/camera 提供摄像头操作函数
显示屏组件 easyeai-api/peripheral_api/display 提供显示屏操作函数
平面几何组件 easyeai-api/algorithm_api/geometry 提供简单几何运算函数
人脸检测组件 easyeai-api/algorithm_api/face_detect 提供人脸检测操作函数
人脸校正组件 easyeai-api/algorithm_api/face_alignment 提供人脸校正操作函数
人脸识别组件 easyeai-api/algorithm_api/face_recognition 提供人脸识别操作函数

主要来看下人脸识别组件。

face_recognition.h的主要内容

//人脸识别初始化函数
int face_recognition_init(rknn_context *ctx, const char * path);
​
//人脸识别执行函数
int face_recognition_run(rknn_context ctx, cv::Mat *face_image, float (*feature)[512]);
​
//人脸识别特征比对函数
float face_recognition_comparison(float *feature_1, float *feature_2, int output_len);
​
//人脸识别释放函数
int face_recognition_release(rknn_context ctx);

一些参数

  • ctx:输入参数,rknn_context句柄
  • path:输入参数,算法模型路径
  • face_image:输入参数,图像数据输入(cv::Mat是Opencv的类型)
  • feature:输出参数,算法输出的人脸特征码

face_alignment.h的主要内容

cv::Mat face_alignment(cv::Mat img, cv::Point2f* points);

geometry.h的主要内容

typedef struct{
    float x;
    float y;
}fPoint_t;
​
typedef struct{
    float left;   //x1
    float top;    //y1
    float right;  //x2
    float bottom; //y2
}fRect_t;
​
typedef struct{
    int32_t x;
    int32_t y;
}s32Point_t;
​
typedef struct{
    int32_t left;   //x1
    int32_t top;    //y1
    int32_t right;  //x2
    int32_t bottom; //y2
}s32Rect_t;
​
//判断点是否在矩形内
extern bool point_in_rect(s32Point_t point, s32Rect_t rect);
​
//计算矩形面积
extern int32_t calc_rect_square(s32Rect_t rect);
​
//找出面积较小矩形
extern s32Rect_t min_rect(s32Rect_t rect1, s32Rect_t rect2);
​
//找出面积较大矩形
extern s32Rect_t max_rect(s32Rect_t rect1, s32Rect_t rect2);
​
//判断矩形是否相交或相切
extern bool rect_is_intersect(s32Rect_t rect1, s32Rect_t rect2);
​
//计算两矩形相交部分面积(若相切,面积也为0)
extern int32_t calc_rect_intersect_square(s32Rect_t rect1, s32Rect_t rect2);
​
//计算[两矩形相交部分面积]与[小矩形面积]之比
extern double calc_intersect_of_min_rect(s32Rect_t rect1, s32Rect_t rect2);
​
//计算两矩形的交并比
extern double calc_intersect_of_union(s32Rect_t rect1, s32Rect_t rect2);

2 代码分析与修改

主要的修改是将红外摄像头采集和活体检测去掉,改用外接RGB摄像头,另外,识别结果的显示,将更多的信息(识别的id,人物名称,耗时等)展示在屏幕上。

2.1 图像采集与显示线程(主线程)

重新定义识别结果:

typedef struct{
    bool bHasFace;     //是否检测到人脸
    bool bMatch;       //是否与注册的人脸匹配
    char idStr[128];   //匹配的人脸的id
    char nameStr[128]; //匹配的人脸的名称
    float similarity;  //匹配的相似度
    uint64_t useTime;  //匹配用时
    uint32_t x1;       //识别到的人脸框的4个点
uint32_t y1;
uint32_t x2;
uint32_t y2;
}Result_t;

官方例程用到了红外摄像头,用于活体检测,此次测试,为了使用电脑屏幕上的人物图片进行人脸检测,去掉了活体检测功能,并换做只使用USB摄像头采集RGB图像进行人脸识别。

主函数逻辑如下,和上篇进行人脸检测的代码逻辑类似。

#define COLOR_RED Scalar(255, 0, 0)
#define COLOR_GREEN Scalar(0, 255, 0)int main(int argc, char **argv)
{
int ret = 0;
    int rgbRet = 0;
    disp_screen_t screen = {0};

char *pRGBbuf = NULL;
int skip = 0;

pthread_t mTid;
Result_t *pResult = NULL;

Mat image;
// 1.打开USB摄像头
ret = usbcamera_init(USB2_0, USB_DIRECT, CAMERA_WIDTH, CAMERA_HEIGHT, 180);
if (ret) {
printf("error: %s, %dn", __func__, __LINE__);
goto exit_donothing;
}

pRGBbuf = NULL;
pRGBbuf = (char *)malloc(IMAGE_SIZE);
if (!pRGBbuf) {
printf("error: %s, %dn", __func__, __LINE__);
ret = -1;
goto exit_freeusb;
}

// 跳过前10帧
skip = 10;
while(skip--) {
ret = usbcamera_getframe(USB2_0, USB_DIRECT, pRGBbuf);
if (ret) {
printf("error: %s, %dn", __func__, __LINE__);
goto exit_freeusb_freebuf;
}
}
​
// 2.创建识别线程,以及图像互斥锁
pthread_mutex_init(&img_lock, NULL);
pResult = (Result_t *)malloc(sizeof(Result_t));
if(NULL == pResult){
goto exit_free_all;
}
memset(pResult, 0, sizeof(Result_t));
if(0 != CreateNormalThread(detect_thread_entry, pResult, &mTid)){
free(pResult);
}
​
// 3.显示初始化
    screen.screen_width = SCREEN_WIDTH;
    screen.screen_height = SCREEN_HEIGHT;
    screen.wins[0].enable = 1;
    screen.wins[0].in_fmt = IMAGE_TYPE_RGB888;
    screen.wins[0].in_w = CAMERA_WIDTH;
    screen.wins[0].in_h = CAMERA_HEIGHT;
    screen.wins[0].rotation = 90;
    screen.wins[0].win_x = 0;
    screen.wins[0].win_y = 0;
    screen.wins[0].win_w = 720;
    screen.wins[0].win_h = 1280;
    ret = disp_init_pro(&screen);
if (ret) {
printf("error: %s, %dn", __func__, __LINE__);
goto exit_free_all;
}
    
// 4.(取流 + 显示)循环
while(1)
    {
// 4.1、取流
pthread_mutex_lock(&img_lock);
ret = usbcamera_getframe(USB2_0, USB_DIRECT, pRGBbuf);
        if (0 != rgbRet) 
        {
            printf("error: %s, %dn", __func__, __LINE__);
pthread_mutex_unlock(&img_lock);
            continue;
        }
algorithm_image = Mat(CAMERA_HEIGHT, CAMERA_WIDTH, CV_8UC3, pRGBbuf);
image = algorithm_image.clone();
pthread_mutex_unlock(&img_lock);
​
// 4.2、显示
        if (pResult->bHasFace) //检测到人脸
        {
            Scalar color;
            //识别到已注册的人脸
            if(pResult->bMatch)
            {
                color = COLOR_GREEN;
                cv::putText(image, std::string("idStr: ") + std::string(pResult->idStr), cv::Point2f(30, 50), cv::FONT_HERSHEY_SIMPLEX, 1.45, CV_RGB(255,0,0),3.0);
                cv::putText(image, std::string("name: ") + std::string(pResult->nameStr), cv::Point2f(30, 100), cv::FONT_HERSHEY_SIMPLEX, 1.45, CV_RGB(255,0,0),3.0);
                cv::putText(image, std::string("similarity: ") + std::to_string(pResult->similarity), cv::Point2f(30, 150), cv::FONT_HERSHEY_SIMPLEX, 1.45, CV_RGB(255,0,0),3.0);
                cv::putText(image, std::string("use time: ") + std::to_string(pResult->useTime), cv::Point2f(30, 200), cv::FONT_HERSHEY_SIMPLEX, 1.45, CV_RGB(255,0,0),3.0);
            }
            else
            {
                color = COLOR_RED;
                cv::putText(image, std::string("unknow face"), cv::Point2f(30, 50), cv::FONT_HERSHEY_SIMPLEX, 1.45, CV_RGB(0,0,255),3.0);
            }
            // 画框
            rectangle(image, Point(pResult->x1, pResult->y1), Point(pResult->x2, pResult->y2), color, 3);
        }
        disp_commit(image.data, IMAGE_SIZE);

        usleep(20*1000);
}
​
exit_free_all:
pthread_mutex_destroy(&img_lock);
exit_freeusb_freebuf:
free(pRGBbuf);
pRGBbuf = NULL;
exit_freeusb:
usbcamera_exit(USB2_0, USB_DIRECT);
exit_donothing:
    return ret;
}

2.2 人脸识别处理

去掉红外摄像头的活体检测逻辑,只使用USB摄像头的图像进行人脸识别
2.png

void *detect_thread_entry(void *para)
{
int ret;
uint64_t start_time,end_time;
Result_t *pResult = (Result_t *)para;
    
// 初始化人脸检测
rknn_context detect_ctx;
std::vector detect_result;
Point2f points[5];
    s32Rect_t rgbRect;
printf("face detect init!n");
ret = face_detect_init(&detect_ctx, "./face_detect.model");
if( ret < 0)
    {
printf("face_detect fail! ret=%dn", ret);
return NULL;
}
    
// 初始化人脸识别
rknn_context recognition_ctx;
float face_feature[512];
printf("face recognition init!n");
ret =  face_recognition_init(&recognition_ctx, "./face_recognition.model");
if( ret < 0)
    {
printf("face_recognition fail! ret=%dn", ret);
return NULL;
}
​
    // 初始化数据库
    database_init();
    // 同步数据库所有数据到内存
faceData_t *pFaceData = (faceData_t *)malloc(MAX_USER_NUM * sizeof(faceData_t));
    memset(pFaceData, 0, MAX_USER_NUM * sizeof(faceData_t));
    int peopleNum = database_getData_to_memory(pFaceData);

// 初始化按键事件
keyEvent_init();
set_event_handle(dataBase_opt_handle);
    
Mat image;
Mat face_algin;
float similarity; //特征值相似度比对
int face_index = 0;
while(1)
{
if(g_delete_all_record)
        {
g_delete_all_record = false;
// 删除库
database_delete_all_record();
// 重载数据库
peopleNum = database_getData_to_memory(pFaceData);
}

        if(algorithm_image.empty()) 
        {
usleep(5);
            continue;
        }

pthread_mutex_lock(&img_lock);
image = algorithm_image.clone();
pthread_mutex_unlock(&img_lock);
        
// 人脸检测,计算出人脸位置
ret = face_detect_run(detect_ctx, image, detect_result);
if(ret <= 0)
        {
// 识别结果数据,复位
memset(pResult, 0 , sizeof(Result_t));
g_input_feature = false;
usleep(1000);
continue;
}
        
        
        rgbRect.left   = (uint32_t)(detect_result[0].box.x);
        rgbRect.top    = (uint32_t)(detect_result[0].box.y);
        rgbRect.right  = (uint32_t)(detect_result[0].box.x + detect_result[0].box.width);
        rgbRect.bottom = (uint32_t)(detect_result[0].box.y + detect_result[0].box.height);
pResult->bHasFace = true;
pResult->x1 = rgbRect.left;
pResult->y1 = rgbRect.top;
pResult->x2 = rgbRect.right;
pResult->y2 = rgbRect.bottom;
for (int i = 0; i < (int)detect_result[0].landmarks.size(); ++i) {
points[i].x = (int)detect_result[0].landmarks[i].x;
points[i].y = (int)detect_result[0].landmarks[i].y;
}
        
// 人脸校正(从图像中裁出人脸)
face_algin = face_alignment(image, points);
        
// 人脸识别,计算特征值
start_time = get_timeval_ms();
face_recognition_run(recognition_ctx, &face_algin, &face_feature);
end_time = get_timeval_ms();
        pResult->useTime = end_time - start_time;
printf("n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>n");
printf("face_recognition_run use time: %llun", pResult->useTime); // 【打印耗时】
        
        // 特征值比对,得出id
similarity = -0.5;
if(peopleNum > 0)
        {
for(face_index = 0; face_index < peopleNum; ++face_index)
            {
similarity = face_recognition_comparison(face_feature, (float *)((pFaceData + face_index)->feature), 512);
if(similarity > 0.5) 
                {
                    break;
                }
}
}
        pResult->similarity = similarity;
printf("similarity:%fn", similarity); //【打印得分】
if((face_index < peopleNum)&&(similarity > 0.5))
        {
            pResult->bMatch = true;
            
// 用id,找名字
            memcpy(pResult->idStr, (pFaceData + face_index)->id, 128);
printf("idStr : %sn", pResult->idStr); //【打印id】
database_id_is_exist(pResult->idStr, pResult->nameStr, sizeof(pResult->nameStr));
printf("person name : %sn", pResult->nameStr); //【打印名字】

            // 按键被按下,更新特征值
if(g_input_feature)
            {
g_input_feature = false;
// 特征值入库
database_add_record(pResult->idStr, pResult->nameStr, (char *)face_feature, sizeof(face_feature));
// 重载数据库
peopleNum = database_getData_to_memory(pFaceData);
}
}
        else
        {
            pResult->bMatch = false;
            
// 按键被按下,录入特征值
if(g_input_feature)
            {
g_input_feature = false;
char idStr[32]={0};
char nameStr[32]={0};
sprintf(idStr, "%05d", face_index+1);
sprintf(nameStr, "people_%d", face_index+1);
// 特征值入库
database_add_record(idStr, nameStr, (char *)face_feature, sizeof(face_feature));
// 重载数据库
peopleNum = database_getData_to_memory(pFaceData);
}
}
        usleep(16*1000);
}

/* 数据库内存数据释放 */
free(pFaceData);
/* 数据库释放 */
    database_exit();
/* 人脸识别释放 */
face_recognition_release(recognition_ctx);
/* 人脸检测释放 */
face_detect_release(detect_ctx);
return NULL;
}

3 测试

测试视频见文章底部视频,这里再放一张测试图片:
3.png

4 总结

本篇介绍了EASY EAI Nano的人脸识别功能,与上篇的人脸检测相比,在检测到有人脸的基础上,通过先录入人脸显示到数据库,可以对比当前识别的谁的脸,实际测试,去掉活体检测功能后,通过外接USB摄像头来识别电脑屏幕上的3个人的多张不同人脸,可以分辨出不同人的人脸。


-----------



附上EASY EAI Nano多人脸识别测试【视频】,详见作者原帖子内容。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • AI
    AI
    +关注

    关注

    87

    文章

    30097

    浏览量

    268368
  • 人脸识别
    +关注

    关注

    76

    文章

    4005

    浏览量

    81756
  • 灵眸
    +关注

    关注

    0

    文章

    19

    浏览量

    3183
收藏 人收藏

    评论

    相关推荐

    基于迅为RK3568/RK3588开发板的AI图像识别方案

    01_官方模型测试 02_人脸识别 03_口罩检测 04_工地防护 05_扑克牌识别 06_手掌关键点检测 07_人脸特征点检测
    发表于 08-28 09:50

    基于迅为RK3588开发板的AI图像识别方案

    迅为RK3568/RK3588开发板AI识别演示方案包括 01_官方模型测试 02_人脸识别 03_口罩检测 04_工地防护 05_扑克牌
    发表于 08-13 11:26

    人脸识别技术的原理介绍

    人脸识别技术是一种基于人脸特征信息进行身份识别的生物识别技术。它通过分析人脸图像,提取
    的头像 发表于 07-04 09:22 1052次阅读

    人脸识别模型训练是什么意思

    人脸识别模型训练是指通过大量的人脸数据,使用机器学习或深度学习算法,训练出一个能够识别和分类人脸的模型。这个模型可以应用于各种场景,如安防监
    的头像 发表于 07-04 09:16 469次阅读

    4G,5G执法记录仪人脸识别人脸比对使用说明

    4G,5G执法记录仪人脸识别人脸比对使用说明
    的头像 发表于 05-13 17:41 929次阅读
    4G,<b class='flag-5'>5</b>G执法记录仪<b class='flag-5'>人脸</b><b class='flag-5'>识别</b>、<b class='flag-5'>人脸</b>比对使用说明

    人脸识别终端 10寸人脸

    终端人脸识别
    深圳市远景达物联网技术有限公司
    发布于 :2024年04月22日 16:01:46

    【LicheeRV-Nano开发套件试用体验】LicheeRV-Nano上的IAI技术应用

    开发板,之前试用过 DUO对其清奇骨骼,小巧的身板,强劲的性能所吸引,在知道其更加强悍的兄弟板出来后,第一时间申请到试用。 此次开发板包含物料比较充分,除了有Nano开发板,还有带触摸的全贴合屏幕
    发表于 03-07 17:32

    【LicheeRV-Nano开发套件试用体验】+智能平板开发

    开发 6.摄像头开发 7.AI人脸识别、运动侦测、姿态检测调试开发 预期成果 1.熟练算能软件工具使用,代码编写调试 2.外设功能驱动达成相应效果 3.网络、音频调通 4.界面设
    发表于 03-06 23:05

    小区无感人脸识别门禁摄像机,多人同时识别通过 #人脸识别 #智能摄像机

    AI人脸识别
    jf_07511428
    发布于 :2024年03月06日 22:53:18

    公司人脸识别考勤门禁摄像机#人脸识别#智能摄像机

    AI人脸识别
    jf_07511428
    发布于 :2024年03月06日 22:52:08

    【LicheeRV-Nano开发套件试用连载体验】+ 实现三麦克纳姆轮小车自主导航

    【LicheeRV-Nano开发套件试用连载体验】+ 实现三麦克纳姆轮小车自主导航 非常感谢被选中成为Sipeed矽速科技、电子发烧友论坛组织的此次试用体验幸运儿,有机会参与
    发表于 03-03 14:20

    EASY-EAI携手Hailo推出高性能、高算力的边缘AI硬件组合

    EASY-EAI与Hailo建立合作关系,共同推出高算力的边缘AI产品组合。
    的头像 发表于 02-21 09:56 761次阅读

    人脸识别技术的原理是什么 人脸识别技术的特点有哪些

    人脸识别技术的原理 人脸识别技术是一种通过计算机以图像或视频为输入,识别、检测、跟踪和分析人脸
    的头像 发表于 02-18 13:52 1640次阅读

    AI视觉识别有哪些工业应用

    AI视觉识别涵盖多种应用,如人脸识别、目标检测和识别、图像分割、行为识别、视频分析等。本篇就简单
    的头像 发表于 11-27 18:05 1168次阅读
    <b class='flag-5'>AI</b>视觉<b class='flag-5'>识别</b>有哪些工业应用

    成都华江信息AI人脸识别原理浅析# 人脸识别

    AI边缘计算
    成都华江信息
    发布于 :2023年11月24日 16:35:54