文章目录
恩智浦NXP RT1062F 本地神经网络人脸识别接口使用详解
一、芯片介绍
NXP MCU级别的人脸识别解决方案利用i.MX RT106F来实现,使开发者轻松便捷地将人脸识别功能添加到他们基于MCU的IoT产品中,这个超小尺寸,集成软件算法和硬件的方案,可以方便开发者进行快速的评估和概念验证开发。SLN-VIZN-IOT开发套件可以离线创建自己的面部模型,而无需进行云连接,从而降低了总体成本和设计复杂性。
这个解决方案最大程度上缩短了上市时间,降低了风险并减少了开发工作,可以使众多OEM厂家更方便地添加人脸识别功能,为智能家居,智能家电,智能玩具和智能工业提供高级用户界面和访问控制功能,而无需Wi- Fi和云连接,解决了许多消费者的隐私问题。
i.MX RT106F是i.MX RT1060系列的成员,于2020年4月份正式量产,主要针对低成本人脸识别应用,基于Arm Coretx-M7内核,主频高达600MHz的高性能实时处理器,除了人脸识别功能外,i.MX RT106F 还有大量可用外设,可以作为多种应用的主芯片。i.MX RT106F已经获得许可,可以运行NXP OASIS 运行库进行人脸识别,其中包括:
摄像头驱动、图像捕获和预处理、人脸检测、人脸跟踪、人脸对比、人脸识别、防欺骗、人脸配置、置信度、人脸识别认证结果、情绪识别、内置安全bootloader,应用程序验证、连接性:MQTT;1W1p,TLS搜索与注册;所有驱动(包含wifi和蓝牙)、RTOS OTW客户端:OTW签名脚本,OTW rollback,图像冗余。
二、摄像头图片获取
在本人实际项目中使用的摄像头获取的格式为YUV422格式,后面使用接口转换为需要的对应接口
通过NXP中的CSI接口获取摄像头的图片,CSI(CMOS Sensor Interface)是专用的图像传感器接口,RT1062的CSI接口支持8位、10位、16位并行接口。CSI模块内嵌DMA因此不需要占用MCU的DMA外设。
CSI中断源码
void CSI_IRQHandler(void)
{
uint32_t csisr = CSI->CSISR;
/* Clear the error flags. */
CSI->CSISR = csisr;
if((csisr & CSI_CSISR_DMA_TSF_DONE_FB1_MASK) != 0)
{
gImageDone = 1;
//gCameraActiveBufferIndex = 1;
gCameraActiveBufferIndexA = 1;
Camera_TransferStop();
//PRINTF("1\n");
}
else if((csisr & CSI_CSISR_DMA_TSF_DONE_FB2_MASK) != 0)
{
gImageDone = 1;
gCameraActiveBufferIndexB = 2;
Camera_TransferStop();
//PRINTF("2\n");
}
//CSI_DriverIRQHandler();
__DSB();
}
通过FLEXIO调取图片信息
- 以下是NXP提供的图片转换接口,第一个参数为摄像头获取的参数,第二个参数为转后图片输出。
void APP_SetPxp_RGB565toRGB888_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_Y8toRGB565_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_Mirror(uint32_t srcBuf, uint32_t dstBuf,uint8_t _MirrorType);
void APP_SetPxp_YUV422toRGB888_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_YUV422toRGB565_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_YUV422toY8_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_YUV422toY8_320_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_YUV422toY8_320_PALM_Rotate(uint32_t srcBuf, uint32_t dstBuf);
void APP_SetPxp_RGB565_640to320_scale(uint32_t srcBuf, uint32_t dstBuf);
- 在实际项目中使用到的是RGB图片和红外IR图片,
//用来存储图片的数组,像素为640*480
__attribute__((aligned(64))) __attribute__((section("SdramSection"))) uint8_t gTempLcddisp[2][640 * 480 * 3];
三、识别接口调用
人脸识别接口初始化结构体,识别模式设置
static OASISLTInitPara_t
init_para =
{
.height = 640,
.width = 480, //图片像素大小
.imgType = OASIS_IMG_TYPE_IR_SINGLE, //人脸识别通道模式选择
.minFace = 100, //人脸存储容量
.memPool = NULL, //内存池
.size = 0, //内存池大小
.cbs = {
OASISLT_EvtHandler,//evtcb //事件响应跳转函数
GetRegisteredFacesHandler,//getface //获取注册人脸
AddNewFaceHandler,//add face //将新注册的人脸加入到链表中
NULL,
NULL,
AdjustBrightnessHandler, //光线处理函数
NULL,
NULL,
oasislite_print
},
.enableFlags = OASIS_ENABLE_LIVENESS,// | OASIS_ENABLE_MULTI_VIEW,
.falseAcceptRate = OASIS_FAR_1_1000000,
.modClass = OASISLT_MODEL_CLASS_LIGHT,
.fastMemBuf = NULL,
.fastMemSize = 0,
};
- 根据不同的识别方式,我们需要对初始化函数中的设置进行更改
typedef enum
{
OASIS_IMG_TYPE_RGB_SINGLE, // input only RGB frame
OASIS_IMG_TYPE_IR_SINGLE, // input only IR frame
OASIS_IMG_TYPE_IR_RGB_DUAL, // IR and RGB frames, do face recognition on IR frame
OASIS_IMG_TYPE_RGB_IR_DUAL, // IR and RGB frames, do face recognition on RGB frame
OASIS_IMG_TYPE_IR_RGB_3D_TRIPLE, // IR, RGB and 3D frames, do face recognition on IR frame
OASIS_IMG_TYPE_RGB_IR_3D_TRIPLE, // IR, RGB and 3D frames, do face recognition on RGB frame
OASIS_IMG_TYPE_NUM,
OASIS_IMG_TYPE_INVALID = 0xFF
} OASISLTImageType_t;
识别接口调用
接口函数使用:
param:rgb888Buf,RGB人脸识别时传入的图像
IRBuf,红外人脸识别时的红外人像图片
剩下的是人脸识别的用户信息结构体
int OASIS_recognition(char* rgb888Buf, char* IRBuf, sFaceRecInfo* _FaceRecInfo, sUserIdNormalInfo* _UserIdNormalInfo)
{
ImageFrame_t RGBFrame = {init_para.height, init_para.width, 0, (unsigned char*)rgb888Buf};
ImageFrame_t IRFrame = {init_para.height, init_para.width, 0, (unsigned char*)IRBuf};
ImageFrame_t* frames[OASISLT_INT_FRAME_IDX_LAST] = {&RGBFrame, &IRFrame, NULL};
int ret = 0;
memset(&gFaceRecInfo, 0xFF, sizeof(sFaceRecInfo));
gFaceRecInfo.faces_count = gParaTable.wRegFaceNum;
gFaceRecInfo.similarity = 0;
gFaceRunMode = FACE_SEARCH_FEATURE;
ret = OASISLT_run_extend(frames, OASIS_DET_REC, init_para.minFace, _UserIdNormalInfo);
memcpy(_FaceRecInfo, &gFaceRecInfo, sizeof(sFaceRecInfo));
//check ret
if(ret != 0)
{
OASISLT_LOGE(">>[oasis]OASISLT_run failed, Expect:0 output:%d\r\n", ret);
}
else
{
OASISLT_LOGI(">>[oasis]OASISLT_run success, Expect:0 output:%d\r\n", ret);
//todo
}
return ret;
}
- 传入参数设置列表
typedef enum
{
OASIS_IMG_FORMAT_RGB888, // 3 channels
OASIS_IMG_FORMAT_BGR888, // 3 channels
/* theses formats are used internal only */
OASIS_IMG_FORMAT_GREY888, // 3 channels
OASIS_IMG_FORMAT_GREY8, // 1 channel
OASIS_IMG_FORMAT_NUM,
OASIS_IMG_FORMAT_INVALID = 0xFF
} OASISLTImageFormat_t;
识别结果
- 识别结果会传入初始化时设置的回调函数中,在以下函数的 OASISLTCbPara_t* para 参数中
static void OASISLT_EvtHandler(ImageFrame_t** frames,
OASISLTEvt_t evt,
OASISLTCbPara_t* para,
void* user_data)
typedef struct
{
FaceBox_t *faceBoxIR; // face rect and landmark on IR image
FaceBox_t *faceBoxRGB; // face rect and landmark on RGB image
uint16_t faceID; // only valid when a face recognized or registered
OASISLTRegisterRes_t regResult; // only valid for registration
OASISLTFaceOrientation_t faceOrientation; //valid for face registration in progress event
OASISLTDeregisterRes_t deregResult; // only valid for deregistration
OASISLTRecognizeRes_t recResult; // only valid for face recognition
OASISLTFaceQualityRes_t qualityResult; // only valid for face quality check event.
//OASISLTFaceMaskCheckRes_t maskResult; // only valid for face mask check event.
OASISLTFaceGlassesCheckRes_t glassesResult; // only valid for face glasses check event.
#define OASISLT_CB_PARA_RESERVED_INT 32
int reserved[OASISLT_CB_PARA_RESERVED_INT]; // this field is reserved for debugging purpose
} OASISLTCbPara_t;
图片质量返回值含义
para->qualityResult;
Byte[0]: Recognition State //识别状态
Byte[1]: Face Count in database //数据库已注册人脸数
Byte[2]: Recognition Quality Check Result: //识别人脸图像质量检测结果
typedef enum {
OASIS_QUALITY_RESULT_FACE_OK , //0.人脸图像质量合格
OASIS_QUALITY_RESULT_FACE_TOO_SMALL, // 1.人脸太小
OASIS_QUALITY_RESULT_FACE_SIDE_FACE, // 2:人脸图像不正
OASIS_QUALITY_RESULT_FACE_BLUR, // 3:人脸图像模糊
OASIS_QUALITY_RESULT_FAIL_LIVENESS_IR, // 4:人脸IR活体失败
OASIS_QUALITY_RESULT_FAIL_LIVENESS_RGB, // 5:人脸RGB活体失败
OASIS_QUALITY_RESULT_FAIL_BRIGHTNESS_DARK, // 6:人脸亮度过黑
OASIS_QUALITY_RESULT_FAIL_BRIGHTNESS_OVEREXPOSURE, // 7:人脸亮度过度曝光
OASIS_QUALITY_RESULT_INVALID = 0xFF // 8:人脸图像质量检测无效
} OASISLTFaceQualityRes_t;
Byte[3]: Recognition Result //识别结果
typedef enum {
OASIS_REC_RESULT_KNOWN_FACE, // 0: 识别为已注册人脸
OASIS_REC_RESULT_UNKNOWN_FACE, // 1: 识别为未注册人脸
OASIS_REC_RESULT_INVALID = 0xFF // 2: 识别无效
} OASISLTRecognizeRes_t;
Byte[4]: Recognition Face ID // 识别已注册人脸ID
Byte[5-8]: Recognition Face Similarity (float type) //识别人脸相似度参数
人脸注册
识别成功后,调用人脸注册函数 FcStoreCharByChar,将用户信息写入指定的Flash中