0
我的购物车
资讯分类
全部资讯
最新活动
商城公告
行业信息
新品推荐
元器件知识
资讯标签
艾为awinic(129) 艾迈斯欧司朗(126) iCEasy商城(85) 英伟达NVIDIA(80) 萤火工场(61) 飞腾派V3(40) 兆易创新(31) 罗彻斯特电子(28) Jetson Orin Nano SUPER 开发套件(21) 资料下载专区(18) 赛昉科技(14) 赛昉科技(StarFive)(13) 小华半导体(13) 芯佰微(12) Seeed矽递科技(11) 灵动微电子(11) 日清纺微电子(9) NVIDIA(8) 飞腾派(8) 上海雷卯Leiditech(8) 微源半导体 LPSemi(8) 龙芯中科(7) GD32VW553-IOT(7) 物奇WuQi(7) 日清纺微电子Nisshinbo(5) 庆科(5) 航顺芯片(5) TROQ创捷电子(4) 创捷电子(4) 开源口碑分享(4) Geehy极海半导体(4) CEM5826-M11(4) 杭晶(HCI)(3) 飞腾派eMMC(3) FTHR-G0001(3) GD32VW553-IOT-V2(3) 罗彻斯特(3) MM32SPIN060G(3) 中国星坤(3) 峰岹科技(3) 村田(2) 野火(2) 小华EVB-HC32F4A0开发板(2) 极海半导体(2) 国产开源硬件(2) 极海(2) 社区评奖活动(2) 芯佰微电子(2) 高通Qualcomm(2) NVIDIA品牌专区(2) 飞腾官网飞腾派(2) 技术问答专区(2) Mini-SPIN0230(2) 飞腾派下载专区(2) 口碑评测(2) 教育优惠申请链接(2) 华润微电子(2) EVB-L0130(2) BeagleBoard.org®(2) iCEsay商城(2) 英伟达初创加速计划(2) 启明云端(2) 弈安云(2) 英迪芯微(2) 龙芯教育派(1) 轮趣科技(1) CEK8902-S905D3(1) 雷卯(1) 飞腾派试用申请链接(1) BeagleBone Black快速入门指南(1) 野火RK3566开发板(1) Jetson AGX Thor 开发套件/模组(1) 618大促(1) 竞买活动(1) 极海半导体(Geehy)(1) Arduino品牌页(1) GD32无线生态专区(1) 一件免邮专区(1) TagoreTech(1) SFH 7018B(1) 一件包邮专区(1) 英伟达 NVIDIA品牌专区(1) GD32VW553-IOT V2版本(1) 618大促专区(1) 欧达可(1) 飞腾派V3版本上新(1) 飞虹半导体(1) 迈巨微(1) GD32VW553-IOT V2(1) 微碧半导体(1) 8月7日竞拍竞买(1) 教育优惠(1) 萤火工场GD32VW553-IOT(1) 台容积电(1) 内存(1) VF202040-A0(1) CEM5825F(1) COMBO模组 EMC3020-PZI5(1) 松科智能(1) 乐动机器人(1) 英伟达 NVIDIA(1) 格力新元(1) 周年抽奖活动(1) 庆科信息(MXCHIP)品牌专区(1) 附件(1) B站风扇视频(1) Jetson AGX Xavier(32GB)(1) 润石(1) NVIDIA DGX™ Spark:桌面级AI超级计算机(1) 飞腾派PRO(1) 微源半导体(1) QCS6490 SOM EVB开发板(1) 附件下载地址(1) 国产自主可控(1) Mini-F5333(1) JETSON_AGX_ORIN_64GB_DEVELOPER_KIT(1) QCS8550 SOM EVB开发板(1) 申请样片:高光效红光OSCONIQ® P 3030, GR QSSPA1.23(1) 华大北斗(1) 开源社区(1) NVIDIA Jetson Orin Nano 开发套件(1) 萤火工场品牌专区(1) 商城下载专区(1) 瑞隆源产品(1) 雷克沙(1) CEM5881-M11(1) Jetson AGX Orin 64GB开发套件(1) 荣湃半导体(2Pai Semi)品牌专区(1) 下载专区(1) 飞腾派专链(1) 世野(Khadas)(1) 中科云(1) Arduino UNO Rev 4 Minima开发板(1) NVIDIA NIM(1) 微雪电子(1) 海芯微(1) NVIDIA Jetson Orin Nano 开发套件(1) Arduino品牌专区(1) 飞腾派调研问卷链接(1) 小脚丫(1) CEM5861G-M11(1) 赛昉科技9折活动券(1) Jetson AGX Orin 64GB开发套件(1) 24GHz毫米波雷达模块(1) 品牌清仓(1) QCS8550 SOM EVB(1) 天微电子商家页(1) 国产毫米波雷达模块(1) 样片申请(1) 海凌科电子(Hi-Link)(1) NVIDIA Jetson Nano 模组(1) QCS6490 SOM EVB(1) EV Board (MM32L0136C7P)(1) 迈巨微电子品牌专区(1)

飞腾派部署人脸识别模型教程

发布时间:2025-12-07

飞腾派部署人脸识别模型教程


AI与物联网深度融合的当下,人脸识别已广泛应用于安防门禁、智慧办公、智能家居、公共服务等场景,成为智能交互核心。国产自主可控开源硬件飞腾派,凭借其高性能与灵活配置轻松实现高精准、低延迟的人脸识别应用!本次教程将分享从部署到测试的全流程。

项目准备

硬件规格:飞腾派

操作系统:飞腾派OS

(飞腾派OS系统下载:‍https://s.iceasy.com/nypTSLI‍)


具体操作:

一、设置编码器:

$ export PATH=$PATH:${YOUR_PATH}/riscv/bin

$ export CC=riscv64-unknown-linux-gnu-gcc

$ export CXX=riscv64-unknown-linux-gnu-g++

二、模型设置

MNN的使用较为简单,使用方法类似TensorFlow 1.x,简要的流程为:

// 创建会话createSession();

// 设置输入getSessionInput();

// 运行会话runSession();

// 获取输出getSessionOutput();

在该逻辑下,将模型的运行预处理,推理,后处理封装为一个模块:

// ultraFace.hpp#ifndef UltraFace_hpp#define UltraFace_hpp

#pragma once

#include "MNN/Interpreter.hpp"

#include "MNN/MNNDefine.h"#include "MNN/Tensor.hpp"#include

"MNN/ImageProcess.hpp"#include <opencv2/opencv.hpp>#include <algorithm>#include <iostream>#include <string>#include <vector>#include <memory>#include <chrono>

#define num_featuremap 4#define hard_nms 1#define blending_nms 2 /* mix nms was been proposaled in paper blaze face, aims to minimize the temporal jitter*/typedef struct FaceInfo {

   float x1;

   float y1;

   float x2;

   float y2;

   float score;

} FaceInfo;

class UltraFace {public:

   UltraFace(const std::string &mnn_path,

             int input_width, int input_length, int num_thread_ = 4, float score_threshold_ = 0.7, float iou_threshold_ = 0.3,

             int topk_ = -1);

   ~UltraFace();

   int detect(cv::Mat &img, std::vector<FaceInfo> &face_list);

private:

   void generateBBox(std::vector<FaceInfo> &bbox_collection, MNN::Tensor *scores, MNN::Tensor *boxes);

   void nms(std::vector<FaceInfo> &input, std::vector<FaceInfo> &output, int type = blending_nms);

private:

   std::shared_ptr<MNN::Interpreter> ultraface_interpreter;

   MNN::Session *ultraface_session = nullptr;

   MNN::Tensor *input_tensor = nullptr;

   int num_thread;

   int image_w;

   int image_h;

   int in_w;

   int in_h;

   int num_anchors;

   float score_threshold;

   float iou_threshold;

   const float mean_vals[3] = {127, 127, 127};

   const float norm_vals[3] = {1.0 / 128, 1.0 / 128, 1.0 / 128};

   const float center_variance = 0.1;

   const float size_variance = 0.2;

   const std::vector<std::vector<float>> min_boxes = {

           {10.0f,  16.0f,  24.0f},

           {32.0f,  48.0f},

           {64.0f,  96.0f},

           {128.0f, 192.0f, 256.0f}};

   const std::vector<float> strides = {8.0, 16.0, 32.0, 64.0};

   std::vector<std::vector<float>> featuremap_size;

   std::vector<std::vector<float>> shrinkage_size;

   std::vector<int> w_h_list;

   std::vector<std::vector<float>> priors = {};

};

#endif /* UltraFace_hpp */

// ultraFace.cpp

#define clip(x, y) (x < 0 ? 0 : (x > y ? y : x))

#include "UltraFace.hpp"

using namespace std;

UltraFace::UltraFace(const std::string &mnn_path,

                    int input_width, int input_length, int num_thread_,

                    float score_threshold_, float iou_threshold_, int topk_) {

   num_thread = num_thread_;

   score_threshold = score_threshold_;

   iou_threshold = iou_threshold_;

   in_w = input_width;

   in_h = input_length;

   w_h_list = {in_w, in_h};

   for (auto size : w_h_list) {

       std::vector<float> fm_item;

       for (float stride : strides) {

           fm_item.push_back(ceil(size / stride));

       }

       featuremap_size.push_back(fm_item);

   }

   for (auto size : w_h_list) {

       shrinkage_size.push_back(strides);

   }

   /* generate prior anchors */

   for (int index = 0; index < num_featuremap; index++) {

       float scale_w = in_w / shrinkage_size[0][index];

       float scale_h = in_h / shrinkage_size[1][index];

       for (int j = 0; j < featuremap_size[1][index]; j++) {

           for (int i = 0; i < featuremap_size[0][index]; i++) {

               float x_center = (i + 0.5) / scale_w;

               float y_center = (j + 0.5) / scale_h;

               for (float k : min_boxes[index]) {

                   float w = k / in_w;

                   float h = k / in_h;

                   priors.push_back({clip(x_center, 1), clip(y_center, 1), clip(w, 1), clip(h, 1)});

               }

           }

       }

   }

   /* generate prior anchors finished */

   num_anchors = priors.size();

   ultraface_interpreter = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(mnn_path.c_str()));

   MNN::ScheduleConfig config;

   config.numThread = num_thread;

   MNN::BackendConfig backendConfig;

   backendConfig.precision = (MNN::BackendConfig::PrecisionMode) 2;

   config.backendConfig = &backendConfig;

   ultraface_session = ultraface_interpreter->createSession(config);

   input_tensor = ultraface_interpreter->getSessionInput(ultraface_session, nullptr);

}

UltraFace::~UltraFace() {

   ultraface_interpreter->releaseModel();

   ultraface_interpreter->releaseSession(ultraface_session);

}

int UltraFace::detect(cv::Mat &raw_image, std::vector<FaceInfo> &face_list) {

   if (raw_image.empty()) {

       std::cout << "image is empty ,please check!" << std::endl;

       return -1;

   }

   image_h = raw_image.rows;

   image_w = raw_image.cols;

   cv::Mat image;

   cv::resize(raw_image, image, cv::Size(in_w, in_h));

   ultraface_interpreter->resizeTensor(input_tensor, {1, 3, in_h, in_w});

   ultraface_interpreter->resizeSession(ultraface_session);

   std::shared_ptr<MNN::CV::ImageProcess> pretreat(

           MNN::CV::ImageProcess::create(MNN::CV::BGR, MNN::CV::RGB, mean_vals, 3,

                                         norm_vals, 3));

   pretreat->convert(image.data, in_w, in_h, image.step[0], input_tensor);

   auto start = chrono::steady_clock::now();

   // run network

   ultraface_interpreter->runSession(ultraface_session);

   // get output data

   string scores = "scores";

   string boxes = "boxes";

   MNN::Tensor *tensor_scores = ultraface_interpreter->getSessionOutput(ultraface_session, scores.c_str());

   MNN::Tensor *tensor_boxes = ultraface_interpreter->getSessionOutput(ultraface_session, boxes.c_str());

   MNN::Tensor tensor_scores_host(tensor_scores, tensor_scores->getDimensionType());

   tensor_scores->copyToHostTensor(&tensor_scores_host);

   MNN::Tensor tensor_boxes_host(tensor_boxes, tensor_boxes->getDimensionType());

   tensor_boxes->copyToHostTensor(&tensor_boxes_host);

   std::vector<FaceInfo> bbox_collection;

   auto end = chrono::steady_clock::now();

   chrono::duration<double> elapsed = end - start;

   cout << "inference time:" << elapsed.count() << " s" << endl;

   generateBBox(bbox_collection, tensor_scores, tensor_boxes);

   nms(bbox_collection, face_list);

   return 0;

}

void UltraFace::generateBBox(std::vector<FaceInfo> &bbox_collection, MNN::Tensor *scores, MNN::Tensor *boxes) {

   for (int i = 0; i < num_anchors; i++) {

       if (scores->host<float>()[i * 2 + 1] > score_threshold) {

           FaceInfo rects;

           float x_center = boxes->host<float>()[i * 4] * center_variance * priors[i][2] + priors[i][0];

           float y_center = boxes->host<float>()[i * 4 + 1] * center_variance * priors[i][3] + priors[i][1];

           float w = exp(boxes->host<float>()[i * 4 + 2] * size_variance) * priors[i][2];

           float h = exp(boxes->host<float>()[i * 4 + 3] * size_variance) * priors[i][3];

           rects.x1 = clip(x_center - w / 2.0, 1) * image_w;

           rects.y1 = clip(y_center - h / 2.0, 1) * image_h;

           rects.x2 = clip(x_center + w / 2.0, 1) * image_w;

           rects.y2 = clip(y_center + h / 2.0, 1) * image_h;

           rects.score = clip(scores->host<float>()[i * 2 + 1], 1);

           bbox_collection.push_back(rects);

       }

   }

}

void UltraFace::nms(std::vector<FaceInfo> &input, std::vector<FaceInfo> &output, int type) {

   std::sort(input.begin(), input.end(), [](const FaceInfo &a, const FaceInfo &b) { return a.score > b.score; });

   int box_num = input.size();

   std::vector<int> merged(box_num, 0);

   for (int i = 0; i < box_num; i++) {

       if (merged[i])

           continue;

       std::vector<FaceInfo> buf;

       buf.push_back(input[i]);

       merged[i] = 1;

       float h0 = input[i].y2 - input[i].y1 + 1;

       float w0 = input[i].x2 - input[i].x1 + 1;

       float area0 = h0 * w0;

       for (int j = i + 1; j < box_num; j++) {

           if (merged[j])

               continue;

           float inner_x0 = input[i].x1 > input[j].x1 ? input[i].x1 : input[j].x1;

           float inner_y0 = input[i].y1 > input[j].y1 ? input[i].y1 : input[j].y1;

           float inner_x1 = input[i].x2 < input[j].x2 ? input[i].x2 : input[j].x2;

           float inner_y1 = input[i].y2 < input[j].y2 ? input[i].y2 : input[j].y2;

           float inner_h = inner_y1 - inner_y0 + 1;

           float inner_w = inner_x1 - inner_x0 + 1;

           if (inner_h <= 0 || inner_w <= 0)

               continue;

           float inner_area = inner_h * inner_w;

           float h1 = input[j].y2 - input[j].y1 + 1;

           float w1 = input[j].x2 - input[j].x1 + 1;

           float area1 = h1 * w1;

           float score;

           score = inner_area / (area0 + area1 - inner_area);

           if (score > iou_threshold) {

               merged[j] = 1;

               buf.push_back(input[j]);

           }

       }

       switch (type) {

           case hard_nms: {

               output.push_back(buf[0]);

               break;

           }

           case blending_nms: {

               float total = 0;

               for (int i = 0; i < buf.size(); i++) {

                   total += exp(buf[i].score);

               }

               FaceInfo rects;

               memset(&rects, 0, sizeof(rects));

               for (int i = 0; i < buf.size(); i++) {

                   float rate = exp(buf[i].score) / total;

                   rects.x1 += buf[i].x1 * rate;

                   rects.y1 += buf[i].y1 * rate;

                   rects.x2 += buf[i].x2 * rate;

                   rects.y2 += buf[i].y2 * rate;

                   rects.score += buf[i].score * rate;

               }

               output.push_back(rects);

               break;

           }

           default: {

               printf("wrong type of nms.");

               exit(-1);

           }

       }

   }

}

三、测试

运行模型,利用图片进行测试

最终仅需55ms左右即可精准完成人脸识别任务!轻松满足智慧安防、智慧家居等应用场景!