简介
相信大部分同学们都已了解或接触过OpenAtom OpenHarmony(以下简称“OpenHarmony”)了,但你一定没在OpenHarmony上实现过人脸识别功能,跟着本文带你快速在OpenHarmony标准设备上基于SeetaFace2和OpenCV实现人脸识别。
项目效果
本项目实现了导入人脸模型、人脸框选和人脸识别三大功能,操作流程如下:
- 录入页面点击右下角按钮,跳转拍摄页面进行拍照;
- 选择一张或多张人脸作为训练模型,并设置对应的名字;
- 选择一张未录入的人脸图片,点击框选按钮实现人脸图片框选功能;
- 最后点击识别,应用会对当前图片进行匹配,最终在界面中显示识别结果。
快速上手
设备端开发
设备端通过OpenCV对图像进行处理并通过Seetaface2对图形数据进行人脸头像的识别,最终输出对应的NAPI接口提供给应用端调用。因此设备端开发主要涉及到OpenCV和Seetaface2的移植以及NAPI接口的开发。
OpenCV库移植
OpenCV是一个功能非常强大的开源计算机视觉库。此库已由知识体系工作组移植到了OpenHarmony中,后期还会将此库合入到主仓。在此库上主仓之前,我们只需要以下几个步骤就可以实现OpenCV的移植使用。
- 通过以下命令下载已经移植好的OpenCV
git clone git@gitee.com:zhong-luping/ohos_opencv.git
- 将OpenCV拷贝到OpenHarmony目录的third_party下
cp -raf opencv ~/openharmony/third_party/
- 适当裁剪编译选项
打开OpenCV目录下的BUILD.gn,如下:
不需要video以及flann功能,将对应的模块注释即可。
import("//build/ohos.gni")
group("opencv") {
deps = [
"//third_party/opencv/modules/core:opencv_core",
// "//third_party/opencv/modules/flann:opencv_flann",
"//third_party/opencv/modules/imgproc:opencv_imgproc",
"//third_party/opencv/modules/ml:opencv_ml",
"//third_party/opencv/modules/photo:opencv_photo",
"//third_party/opencv/modules/dnn:opencv_dnn",
"//third_party/opencv/modules/features2d:opencv_features2d",
"//third_party/opencv/modules/imgcodecs:opencv_imgcodecs",
"//third_party/opencv/modules/videoio:opencv_videoio",
"//third_party/opencv/modules/calib3d:opencv_calib3d",
"//third_party/opencv/modules/highgui:opencv_highgui",
"//third_party/opencv/modules/objdetect:opencv_objdetect",
"//third_party/opencv/modules/stitching:opencv_stitching",
"//third_party/opencv/modules/ts:opencv_ts",
// "//third_party/opencv/modules/video:opencv_video",
"//third_party/opencv/modules/gapi:opencv_gapi",
]
}
- 添加依赖子系统的part_name,编译框架子系统会将编译出的库拷贝到系统文件中。
此项目中我们新建了一个SeetaFaceApp的子系统,该子系统中命名part_name为SeetafaceApi,所以我们需要在对应模块中的BUILD.gn中加上part_name=“SeetafaceApi”
以module/core为例:
ohos_shared_library("opencv_core"){
sources = [ ... ]
configs = [ ... ]
deps = [ ... ]
part_name = "SeetafaceApi"
}
- 编译工程需要添加OpenCV的依赖。
在生成NAPI的BUILD.gn中添加以下依赖:
deps += [ "//third_party/opencv:opencv" ]
至此,人脸识别中OpenCV的移植使用完成。
SeetaFace2库移植
SeetaFace2是中科视拓开源的第二代人脸识别库。包括了搭建一套全自动人脸识别系统所需的三个核心模块,即:人脸检测模块FaceDetector、面部关键点定位模块FaceLandmarker以及人脸特征提取与比对模块 FaceRecognizer。
关于SeetaFace2的移植请参照文档:SeetaFace2移植开发文档。
NAPI接口开发
关于OpenHarmony中的NAPI开发,参考视频:
OpenHarmony中napi的开发视频教程。本文将重点讲解NAPI接口如何实现OpenCV以及SeetaFace的调用。
- 人脸框获取的NAPI接口的实现。
int GetRecognizePoints(const char *image_path);
此接口主要是通过应用层输入一张图片,通过OpenCV的imread接口获取到图片数据,并通过人脸检测模块FaceDetector分析获得图片中所有的人脸矩形框(矩形框是以x,y,w,h的方式)并将人脸框矩形以数组的方式返回到应用层。
人脸框矩形获取的主要代码如下:
static int RecognizePoint(string image_path, FaceRect *rect, int num)
{
if (rect == nullptr) {
cerr << "NULL POINT!" << endl;
LOGE("NULL POINT! \n");
return -1;
}
seeta::ModelSetting::Device device = seeta::ModelSetting::CPU;
int id = 0;
/* 设置人脸识别模型。*/
seeta::ModelSetting FD_model( "/system/usr/model/fd_2_00.dat", device, id );
seeta::ModelSetting FL_model( "/system/usr/model/pd_2_00_pts81.dat", device, id );
seeta::FaceDetector FD(FD_model);
seeta::FaceLandmarker FL(FL_model);
FD.set(seeta::FaceDetector::PROPERTY_VIDEO_STABLE, 1);
/* 读取图片数据 */
auto frame = imread(image_path);
seeta::cv::ImageData simage = frame;
if (simage.empty()) {
cerr << "Can not open image: " << image_path << endl;
LOGE("Can not open image: %{public}s", image_path.c_str());
return -1;
}
/* 图片数据进行人脸识别处理 ,获取所有的人脸框数据对象*/
auto faces = FD.detect(simage);
if (faces.size <= 0) {
cerr << "detect " << image_path << "failed!" << endl;
LOGE("detect image: %s failed!", image_path.c_str());
return -1;
}
for (int i = 0; (i < faces.size && i < num); i++) {