
基于OpenHarmony 5.0.0Release的openCV人脸检测应用
一、什么是OpenCV OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它由一系列的C函数和少量C++类构成,同时提供Python、Java和MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV具有极广的应用领域,它包括但不限于: 人脸识别和物体识别:这是OpenCV的一项重要功能,应用
一、什么是OpenCV
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它由一系列的C函数和少量C++类构成,同时提供Python、Java和MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV具有极广的应用领域,它包括但不限于:
- 人脸识别和物体识别:这是OpenCV的一项重要功能,应用在许多领域,如安全监控、交互设计等。
- 图像和视频分析:如图像增强、图像分割、视频跟踪等。
- 图像合成和3D重建:在图像处理和计算机视觉领域,OpenCV可以用于创建AR或VR效果,生成3D模型等。
- 机器学习:OpenCV内置了大量的机器学习算法,可以用于图像分类、聚类等任务。
- 深度学习:OpenCV中的dnn模块提供了一系列深度学习模型的接口,用户可以加载预训练模型进行图像识别、目标检测等任务。
三、本项目介绍
本项目参考opencv_app_sample应用实现,本项目是基于Haar 级联实现人脸检测,haarcascade_frontalface_alt.xml文件在rawfile文件夹。后续会基于FaceDetectorYN
和FaceRecognizerSF
是实现人脸检测、比对。两种实现方式差别较大,感兴趣可以自行搜索。
项目流程梳理
三、项目实操
3.1、环境准备
设备环境:OH4.1及以上设备
开发环境:DevEco Studio 4.1 Release(构建版本:4.1.0.400)
SDK版本:4.1.9.2 Release full sdk
源码地址:https://gitee.com/MIKECODE/opencv_face_demo.git
3.2、修改代码
首先使用git clone https://gitee.com/MIKECODE/opencv_face_demo.git 获取代码并用DevEco4.1打开项目文件。
3.2.1、获取openCV库
下载opencv-4.5.5-ndk,解压后将libs下内容复制到 entry/libs 目录。(项目限制空间大小,所以库文件需要单独下载)
3.2.2、项目签名
- 打开项目结构(快捷键Ctrl+Alt+Shift+S)
3.3、运行代码
- 确保以上步骤完成,用数据线连接设备和pc,点击run,应用即可安装至设备。
首页 | 切换图片 | 识别中 | 识别完成 |
---|---|---|---|
使用说明
- 首先打开应用,点击FaceDetect开始人脸识别。
- 识别完成后点击Recover开始滑动文件名进行图片切换
四、如何集成FaceDetectorYN和FaceRecognizerSF
FaceDetectorYN和FaceRecognizerSF依赖神经网络实现人脸识别,准确率高,速度快,目前还在调试中,可以按以下方法接着调试。
4.1、修改entry/src/main/ets/workers/dealPictureWorker.ets
修改以调用getFaceFeatures
函数。
workerPort.onmessage = (e: MessageEvents) => {
const path = e.data['path'] as string;
const fileName = e.data['fileName'] as string;
const context = e.data['context'] as Context;
Logger.info(TAG, `worker onmessage ${fileName}`);
let pixelInfo = opencv.getFaceFeatures(context.resourceManager, path, fileName);
// let pixelInfo: opencv.PixelInfo = opencv.faceDetect(context.resourceManager, path, fileName);
// Logger.info(TAG, `pixelInfo buffSize: ${pixelInfo.buffSize}`);
//
// let opts: image.InitializationOptions = {
// editable: true,
// pixelFormat: image.PixelMapFormat.RGBA_8888,
// size: { height: pixelInfo.rows, width: pixelInfo.cols }
// }
// image.createPixelMap(pixelInfo.byteBuffer, opts, (error, pixelMap) => {
// if (error) {
// Logger.error(TAG, `Failed to create pixelmap error_code ${error.code}`);
// } else {
// Logger.info(TAG, 'Succeeded in creating pixelmap.');
// workerPort.postMessage(pixelMap);
// }
// })
}
4.2、修改src/main/cpp/image_basic/faceDetect.cpp
这里是getFaceFeatures
函数的实现,目前调用会报错,可以根据报错内容修改
// 获取人脸特征值接口
napi_value GetFaceFeatures(napi_env env, napi_callback_info info) {
OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "GetFaceFeatures Begin");
napi_value result = NapiGetNull(env);
size_t argc = 3;
napi_value argv[3] = {nullptr};
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
size_t strSize;
char strBuf[256];
napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);
std::string fileDir(strBuf, strSize);
OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "fileDir:%{public}s", fileDir.c_str());
napi_get_value_string_utf8(env, argv[2], strBuf, sizeof(strBuf), &strSize);
std::string fileName(strBuf, strSize);
OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "fileName:%{public}s", fileName.c_str());
cv::Mat srcImage;
if (!GetMatFromRawFile(env, argv[0], fileDir, fileName, srcImage)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Get Mat from rawfile failed!.");
return result;
}
// 确保图像为三通道RGB
if (srcImage.channels() == 1) {
cv::cvtColor(srcImage, srcImage, cv::COLOR_GRAY2RGB);
} else if (srcImage.channels() == 4) {
cv::cvtColor(srcImage, srcImage, cv::COLOR_BGRA2RGB);
}
// 调整图像大小为 320*320
cv::Mat resizedImage;
cv::resize(srcImage, resizedImage, cv::Size(320, 320));
// 转换图像数据类型为float32并归一化
cv::Mat floatImage;
resizedImage.convertTo(floatImage, CV_32F, 1.0 / 255.0);
// 创建符合 [1, 3, 320, 320] 格式的张量
cv::Mat blob = cv::dnn::blobFromImage(floatImage, 1.0, cv::Size(320, 320), cv::Scalar(), true, false);
// 创建人脸检测器
cv::Ptr<cv::FaceDetectorYN> detector =
cv::FaceDetectorYN::create("/data/storage/el2/base/haps/entry/files/yunet_s_320_320.onnx", "", cv::Size());
if (!detector) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Failed to create face detector!");
return result;
}
// 设置输入大小为 320*320
detector->setInputSize(cv::Size(320, 320));
cv::Mat faces;
try {
// 传入预处理后的张量
detector->detect(floatImage, faces);
} catch (const cv::Exception &e) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "OpenCV exception: %s", e.what());
return result;
}
if (faces.rows > 0) {
// 创建人脸识别器
cv::Ptr<cv::FaceRecognizerSF> recognizer =
cv::FaceRecognizerSF::create("/data/storage/el2/base/haps/entry/files/face_recognizer_fast.onnx", "");
if (!recognizer) {
OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "Failed to create face recognizer!");
return result;
}
cv::Mat alignedFace;
recognizer->alignCrop(srcImage, faces.row(0), alignedFace);
cv::Mat faceFeature;
recognizer->feature(alignedFace, faceFeature);
// 将特征值转换为 JavaScript 数组
napi_create_array(env, &result);
for (int i = 0; i < faceFeature.cols; ++i) {
napi_value value;
napi_create_double(env, faceFeature.at<float>(0, i), &value);
napi_set_element(env, result, i, value);
}
}
OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "GetFaceFeatures End");
return result;
}
4.3、先安装应用,再手动上传onnx文件到项目目录,最后再执行FaceDetect
4.2中有加载部分onnx文件,目前还没实现文件复制,通过hdc手动推送两个文件到/data/app/el2/100/base/com.demo.opencvface/haps/entry/files,文件在项目rawfile目录
4.4、根据报错排查
E OpenCV exception: OpenCV(4.5.5) C:/Users/Administrator/DevEcoStudioProjects/MyApplication15/libtest/src/main/cpp/opencv/modules/dnn/src/dnn.cpp:1559: error: (-204:Requested object was not found) Layer with requested id=-1 not found in function 'getLayerData'
五、其他
待更新
更多推荐
所有评论(0)