TanyWang

  • 1 主题
  • 1 帖子
  • 250 积分
  • 身份:LV1 技术小白
  • E币:235

【大联大世平恩智浦人脸识别】MIMX RT106F人脸识别测评报告

2021-9-1 23:03:25 显示全部楼层
RT106F评测报告
一、  从开箱到上电运行demo
首先感谢大联大官方及其面包板社区给了这一次RT106F评测的机会,因为在很早之前就研究过恩智浦半导体设计的跨界处理器,因此对IMX RT系列的处理器还是有比较深的了解。闲话不多说下面展开评测叙述。
这里开箱报告我就不说了,因为小编当时拿到板卡之后就迫不及待的把盒子拆碎了,然后分离了摄像头FPC线对两块板子的PCB做了一个总览,不得不说这块板子做的十分的精湛。有兴趣的小伙伴可以去面包板社区搜索。
5.jpg 4.jpg 3.jpg 2.jpg 1.jpg
碍于工程习惯,在保证板子没问题的情况下就去官网下载了原理图、编程手册及其SDK包。这款跨界处理器做的人脸识别SDK里面由于涉及了众多的启动文件,目前只适配了官方编译工具MCUXpresso IDE的SDK包,习惯拿KEIL、IAR编程做项目的小伙伴们可能就有点不大习惯了,不多都是大同小异实际上官方的编译工具优化编译速度更加可观。按照《MCU VIZNAS Solution Developer’s Guide》这篇指导手册很快就创建了workspace并实现了编译,如果需要debug就需要一个对Cortex M7下载的编译器,如果是选择J-Link就需要J-Link-ob或者J-Link V9及其以上的版本,否则就会下载出错。
官方指导手册上标注了怎么利用J-Link和转接板来对板卡编程,由于小编没有这种桥接板于是利用杜邦线和10pin的排线做做了一个简陋的SWD转接
6.jpg
说到这里,官方的原理设计图好像还有一个小问题,就是J5这个10Pin排插座的第9引脚原理图上是和第3、5、9引脚并行接地的,可事实上用万用表量的时候第9引脚并不是接地的。下面附上原理图J5部分。
7.jpg
编译完成后就debug烧录仿真,由于bootload的启动项多且繁琐所以烧录的时候校验项会比较多,烧录的时间就会有所偏长。
8.jpg
要怎么验证这个SDK函数呢?这时候需要用到《MCU VIZNAS Solution User’s Guide》这本指导手册,在win10系统下搜索相机,打开USB相机(笔记本有默认需要切换一下)将摄像头对着有人脸的环境下就会出现人脸抓框:
9.jpg
然后提供了四个按键分别为注册人脸,取消注册人脸、摄像头切换、和视频上的图形显示开关。然后介绍了怎么使用shell工具用命令实现功能,这里我为自己注册了一张人脸并精准识别。
10.jpg
恩智浦将这款产品定义在物联网类中做人脸识别开关锁方向,但是值得一提的是这款板卡对环境光的要求实在太高,有时候环境光稍暗或者光线较强都很难注册人脸身份,这里是否需要写一个软件宽动态程序进行滤光或者更换硬件宽动态摄像头来进行适配?
二、  SDK相关功能函数剖析
1.人脸识别的准确率及其识别效率分析
做这个分析之前呢,我们需要了解一些这个人脸识别程序框架,否则就不能真正理解这个人脸识别是怎么做到的。
11.jpg
初次看到这里我以为官方借鉴了OpenCV的源码函数,并进行了修剪裁枝,但从函数对比上来看不是这样的。OpenCV和OpenVINO的deteceted原理都是一样的,都需要借鉴外部的IR文件,虽然SDK中也写了文件系统,可能是碍于调用延时或者函数框架支持度不太完善没有选择去借鉴。为了进一步保证图像数据的快速更新,在摄像头取帧的时候选用了320*240像素的QVGA模式,然后根据这个图像帧官方就做了320*240大小的16位数组,这里就可以看出图像数据是RGB565格式的了,为了方便计算最终把RGB格式转换成了YUV格式的了。然后建立了大小为10368的16位数组记录人脸特征元素提供给机器学习去训练(在线学习),然后输出关键面部识别元素数据,后续的摄像头进来的每一帧数据根据这样的特征元素信息进行匹配校验,实现人脸识别。
总体来说实时性还是比较好的,但在图像移动中还是有明显的延时,毕竟内置了2D GPU加速器来应对矩阵计算校验。人脸抓框响应很快识别效率非常可观,比起yolo用数据集生成的权重文件来人脸识别那可是非常效率的。不过短板也摆在这里毕竟数据集单一,只要正脸在摄像头的取帧中程序才会响应抓框函数,如果不是那么的正面或者比较侧面这个函数就不会被激活。下面解析一下这个抓框函数。
static void draw_icon(uint16_t *pIcon, int x, int y, int w, int h, int alpha, uint16_t *pCanvasBuffer)
{
    for (int i = y; i < (y + h); i++)
    {
        for (int j = x; j < (x + w); j++)
        {
            if (*pIcon <= alpha)
                *(pCanvasBuffer + i *APP_AS_WIDTH + j) = *pIcon++;
            else
                pIcon++;
        }
    }
}
static void draw_fillrect(int x, int y, int w, int h, int rect_color, uint16_t *pCanvasBuffer)
{
    for (int i = x; i < (x + w); i++)
        for (int j = y; j < (y + h); j++)
            *(pCanvasBuffer + j * APP_AS_WIDTH+ i) = rect_color;
}
第一个子函数确定人脸肖像位置,这个函数运行在2D GPU上做矩阵运算,然后把确定好人脸肖像的起始坐标记录下来并传递给第二子函数开始描绘矩形框,人脸抓框就完成了。
人脸识别的机器学习框架会去扫描面部特征,一般来说会去检测两眼,鼻子,两个嘴唇的边缘这5个特征点,全部条件满足就认为识别到了一个人脸框。对于身份识别就会集中在68个人脸轮廓特征,甚至128个特征点,来精确识别人的ID身份。所以在戴口罩的前提下遮住了鼻子和嘴唇机器学习Tengine就判别失败了。
12.jpg
然后就是人脸身份识别,函数为了快速响应就把这个注册的结果放在了RAM里面做了,所以一旦掉电就必须重新注册,因此在产品化的同时还需注意这个细节。另外由于RAM大小限制,SDK中最大的注册人数为8人,这个有更大需求的需要另行修改。在满足活体检测及其config设置的选项下识别精准度还是异常的高的。基本上没有误识别,毕竟大数据量的人脸咱也没法去验证。
2.活体检测及其面部识别分析验证
板载了一个带菲涅尔透镜的红外感应器,不过感觉效果不是特别的好,有时候放在人面有点异动板卡检测效果就从1变成0了,不过稳定下来还是1。程序在注册、识别、删除人脸信息的时候都会调用这个判断机制。
static void UIInfo_UpdateFaceInfo(uint16_t *pBufferAddr, QUIInfoMsg infoMsg)
{
    char tstring[64];
    std::string name = infoMsg.name;
    switch (s_OasisEvents)
    {
        case kEvents_API_Layer_NoEvent:
            break;
        case 1 << kEvents_API_Layer_FaceExist:
        {
            sprintf(tstring, "Already Registered");
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 70, 10, 0x0, RGB565_RED, OPENSANS16, pBufferAddr);
        }
        break;
        case 1 << kEvents_API_Layer_DeregFailed:
        {
            sprintf(tstring, "Remove Failed");
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 70, 10, 0x0, RGB565_RED, OPENSANS16, pBufferAddr);
        }
        break;
        case 1 << kEvents_API_Layer_DeregSuccess:
        {
            sprintf(tstring, "%s removed", name.c_str());
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 70, 10, 0x0, RGB565_GREEN, OPENSANS16, pBufferAddr);
        }
        break;
        case 1 << kEvents_API_Layer_RegSuccess:
        {
            sprintf(tstring, "%s Added", name.c_str());
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 100, 100, 0x0, RGB565_GREEN, OPENSANS16, pBufferAddr);
        }
        break;
        case 1 << kEvents_API_Layer_RegFailed:
        {
            sprintf(tstring, "Registration Failed");
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 70, 10, 0x0, RGB565_RED, OPENSANS16, pBufferAddr);
        }
        break;
        case 1 << kEvents_API_Layer_RecSuccess:
        {
            uint16_t *pIcon;
            sprintf(tstring, "Unlocked");
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 120, 10, 0, RGB565_GREEN, OPENSANS16, pBufferAddr);
            pIcon = (uint16_t *)welcomehome_320x122;
            draw_icon(pIcon,CAMERA_SURFACE_SHIFT, 60, welcomehome_W, welcomehome_H, 0xffff, pBufferAddr);
        }
        break;
        case 1 << kEvents_API_Layer_RecFailed:
        {
            sprintf(tstring, "Recognition Timeout");
            draw_text(tstring,CAMERA_SURFACE_SHIFT + 70, 10, 0x0, RGB565_RED, OPENSANS16, pBufferAddr);
        }
        break;
        default:
            break;
    }
}
至于人脸识别这里没有具体的API函数去分析,不过类似于市面上常用的机器学习算法一样,函数中大概是利用了112个关键脸部节点去做的Machine Leaning,类似于DLIB用面部68个特征点去象征性匹配识别一般,这里因为没有更多的参照API也不敢轻易的下结论。
3.处理图像函数的硬件资源讲解
这里先简要概述一下RT106F的整体属性吧。首先呢RT106F跨界处理器定义在边缘端的信息处理,这块板卡充分提现了这个概念,高性能M7核实时处理图像数据和图像加速计算,然后板载WIFI和BLE天线供接入网络端,这样就能在云端实时的看到数据的更新和操作传达。
13.jpg
特别有趣的一个地方就是RT106F的机器学习核—OASIS。至于这个机器学习内核文档也没有具体的描述,然后在官网下看到NXP的工程师回答了这个问题:
14.jpg
大概意思就是内部定义了人脸识别检测算法库,这个库不开源,使用者不能进行修改。这正好印证了我上述的机器学习剖析那一章节的内容。
机器学习引擎也是基于OASIS和视觉库(Mini CV)的结合,只不过这个算法引擎运行在2D GPU的图像加速设备中(可以理解额外的一个DSP核),然后通过Memory Manager库来从本地把需要进行复杂计算的数据放在DSP上,再将DSP运算完成的结果返回到本地执行结果输出。这有点像OpenCL的传输机制了,Intel核显与本地交互不就是这个原理么。然后就是Mini CV了,借鉴了OpenCV抓框、字符描述、图像颜色通道的转换等等函数,用Mini描述也是应景了。
总结:
优点:响应速度快,计算准确,小巧灵活,计算边缘性较强。
待改善:机器学习库不开源、RGB图像对环境光要求较高、person_id数量没做提升处理。
总体来说这款人脸识别对于智能家居开关锁的设计恰到好处,在离线人脸识别中是一个很大的技术进阶。

视频: 2021-09-01-22-32-04.part01.rar (5 MB, 下载次数: 0)