OpenHarmony OpenCV应用样例开发

news2024/11/27 12:48:13

背景

OpenCV 介绍

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它由一系列的 C 函数和少量 C++ 类构成,同时提供 Python、Java 和 MATLAB 等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

OpenCV 具有极广的应用领域,它包括但不限于:

  • 人脸识别和物体识别:这是 OpenCV 的一项重要功能,应用在许多领域,如安全监控、交互设计等。
  • 图像和视频分析:如图像增强、图像分割、视频跟踪等。
  • 图像合成和 3D 重建:在图像处理和计算机视觉领域,OpenCV 可以用于创建 AR 或 VR 效果,生成 3D 模型等。
  • 机器学习:OpenCV 内置了大量的机器学习算法,可以用于图像分类、聚类等任务。
  • 深度学习:OpenCV 中的 dnn 模块提供了一系列深度学习模型的接口,用户可以加载预训练模型进行图像识别、目标检测等任务。

本文主要介绍 OpenHarmony 如何用 opencvlib 进行应用样例开发

应用开发

创建 HAP
  • 通过 DevEcoStudio 创建项目“File->New->Create Project"创建一个工程

  • 工程创建完毕后,界面入口为 Index.ets

引用 OpenCV lib 库
  • 引入 opencv 头文件库,放在 include 目录下

  • 引入 lib 库,放在 libs 目录下

  • 修改 CMAKE

  • 增加 common 头文件和 cpp 文件

//
// Created on 2024/3/5.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef OpencvSample_common_H
#define OpencvSample_common_H

#include <string>
#include <stdio.h>
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <vector>
#include "opencv2/opencv.hpp"
#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "hilog/log.h"
#include "napi/native_api.h"
#include "rawfile/raw_file_manager.h"
#include "rawfile/raw_file.h"
#include "rawfile/raw_dir.h"

#define GLOBAL_RESMGR (0xFFEE)
constexpr int32_t RGB_565 = 2;
constexpr int32_t RGBA_8888 = 3;

constexpr int32_t STR_MAX_SIZE = 200;
constexpr int32_t LONG_STR_MAX_SIZE = 1024;
constexpr int32_t ERR_OK = 0;
constexpr int8_t NO_ERROR = 0;
constexpr int8_t ERROR = -1;
constexpr uint8_t PARAM0 = 0;
constexpr uint8_t PARAM1 = 1;
constexpr uint8_t PARAM2 = 2;
constexpr uint8_t PARAM3 = 3;
constexpr uint8_t PARAM4 = 4;
constexpr uint8_t PARAM5 = 5;
constexpr uint8_t PARAM6 = 6;
constexpr uint8_t PARAM7 = 7;
constexpr uint8_t PARAM8 = 8;
constexpr uint8_t PARAM9 = 9;
constexpr uint8_t PARAM10 = 10;
constexpr uint8_t PARAM11 = 11;
constexpr uint8_t PARAM12 = 12;

constexpr int32_t ARGS_ONE = 1;
constexpr int32_t ARGS_TWO = 2;
constexpr int32_t ONLY_CALLBACK_MAX_PARA = 1;
constexpr int32_t ONLY_CALLBACK_MIN_PARA = 0;

struct CallbackPromiseInfo {
    napi_ref callback = nullptr;
    napi_deferred deferred = nullptr;
    bool isCallback = false;
    int32_t errorCode = 0;
};

template <typename T> void FreeMemory(T *p) {
    if (p == nullptr) {
        return;
    }
    delete p;
    p = nullptr;
}

template <typename T> void FreeMemoryArray(T *p) {
    if (p == nullptr) {
        return;
    }
    delete[] p;
    p = nullptr;
}
#define NAPI_RETVAL_NOTHING
#define NAPI_CALL_BASE(env, theCall, retVal)                                                                           \
    do {                                                                                                               \
        if ((theCall) != 0) {                                                                                          \
            return retVal;                                                                                             \
        }                                                                                                              \
    } while (0)

#define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr)
#define NAPI_CALL_RETURN_VOID(env, theCall) NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING)

extern bool GetMatFromRawFile(napi_env env, napi_value jsResMgr, const std::string &rawfileDir,
                              const std::string &fileName, cv::Mat &srcImage);
extern bool cvtMat2Pixel(cv::InputArray _src, cv::OutputArray &_dst, int code);
extern napi_value NapiGetNull(napi_env env);
extern uint32_t GetMatDataBuffSize(const cv::Mat &mat);
extern bool CreateArrayBuffer(napi_env env, uint8_t *src, size_t srcLen, napi_value *res);
extern napi_value NapiGetUndefined(napi_env env);
extern napi_value GetCallbackErrorValue(napi_env env, int32_t errCode);
extern napi_value NapiGetBoolean(napi_env env, const bool &isValue);
extern uint32_t GetMatDataBuffSize(const cv::Mat &mat);
extern void SetCallback(const napi_env &env, const napi_ref &callbackIn, const int32_t &errorCode,
                        const napi_value &result);
extern void SetPromise(const napi_env &env, const napi_deferred &deferred, const int32_t &errorCode,
                       const napi_value &result);
extern void ReturnCallbackPromise(const napi_env &env, const CallbackPromiseInfo &info, const napi_value &result);
extern napi_value JSParaError(const napi_env &env, const napi_ref &callback);
extern void PaddingCallbackPromiseInfo(const napi_env &env, const napi_ref &callback, CallbackPromiseInfo &info,
                                       napi_value &promise);
extern bool WrapJsPixelInfoInfo(napi_env env, cv::Mat &outMat, napi_value &result);

#endif //OpencvSample_common_H
  • 增加灰度转换方法

using namespace std;
using namespace cv;
static const char *TAG = "[opencv_img2Gray]";

napi_value Img2Gray(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "Img2Gray 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());

    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;
    }

    Mat srcGray;
    cvtColor(srcImage, srcGray, COLOR_RGB2GRAY);

    // 將图像转换为pixelMap格式
    Mat outMat;
    cvtMat2Pixel(srcGray, outMat, RGBA_8888);
    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "outMat size: %{public}d, cols:%{public}d, rows:%{public}d",
                 outMat.total(), outMat.cols, outMat.rows);

    napi_create_object(env, &result);
    bool retVal = WrapJsPixelInfoInfo(env, outMat, result);
    if (!retVal) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "WrapJsInfo failed!.");
    }

    return result;
}
  • 导出 //hello.cpp
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"img2Gray", nullptr, Img2Gray, nullptr, nullptr, nullptr, napi_default, nullptr}
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END
  • 导出接口 //index.d.ts
import resourceManager from '@ohos.resourceManager';

export interface PixelInfo {
  rows: number;
  cols: number;
  buffSize: number;
  byteBuffer: ArrayBuffer;
}

export const add: (a: number, b: number) => number;
export const img2Gray: (resmgr: resourceManager.ResourceManager, path: string, file: string) => PixelInfo;
  • 在页面添加交互 // index.ets
Column() {
  Image(this.isGray ? this.imagePixelMap : $rawfile('lena.jpg'))
    .margin({ left: 24, right: 24 })
    .objectFit(ImageFit.Contain)
    .id('backBtn')
  }
  .width('100%')
  .height('60%')
  .alignItems(HorizontalAlign.Center)
  .justifyContent(FlexAlign.Start)

  Row() {
    Button($r('app.string.image_gray'), { type: ButtonType.Capsule })
      .backgroundColor(this.isGray ? Color.Gray : Color.Blue)
      .margin({ left: 24 })
      .width('30%')
      .id('imageGray')
      .enabled(this.isGray ? false : true)
      .onClick(() => {
        let pixelInfo: testNapi.PixelInfo = testNapi.img2Gray(getContext().resourceManager, '', 'lena.jpg');
        Logger.info(TAG, `pixelInfo buffSize: ${pixelInfo.buffSize}`);

        let opts: image.InitializationOptions = {
          editable: true,
          pixelFormat: this.pixelMapFormat,
          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.');
            this.imagePixelMap = pixelmap;
          }
        })
        this.isGray = true;
    })

    Button($r('app.string.image_recover'), { type: ButtonType.Capsule })
      .backgroundColor(Color.Blue)
      .width('30%')
      .id('imageRecover')
      .onClick(() => {
        this.isGray = false;
      })
    }
    .width('100%')
  • 展示

总结

  • 可以用 nativec++ 方式导入 opencv 库直接开发应用,目前实现了一个简单接口,后面会实现场景应用

  • 目前只能做到可用,还有以下问题:

    • 需要 NAPI 接口进行 ArkTS 和 C/C++ 交互
    • 速度比较慢,是否可以通过 GPU 加速
    • Arkts 和 native 交互多,考虑转用 xcomponent 方式

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1556907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四轴飞行器玩具软件技术服务

广东四轴飞行器玩具软件技术服务。 东莞市酷得智能科技有限公司成立于广东省东莞市松山湖高新产业园区&#xff0c;我们专注于电子类方案开发设计&#xff0c;提供多类型的IC采购服务。 酷得的益智玩具软件方案定制服务旨在为客户提供一站式的解决方案&#xff0c;帮助其在竞争…

【AcWing】蓝桥杯集训每日一题Day9|区间合并|1343.挤牛奶(C++)

1343.挤牛奶 1343. 挤牛奶 - AcWing题库难度&#xff1a;简单时/空限制&#xff1a;1s / 64MB总通过数&#xff1a;4627总尝试数&#xff1a;13242来源&#xff1a;usaco training 1.3算法标签区间合并差分 题目内容 每天早上 5 点&#xff0c;三名农夫去牛场给奶牛们挤奶。 …

ROS 2边学边练(6)-- 何为参数(parameters)

概念 这一知识点&#xff0c;应该很好理解&#xff0c;参数就是节点的属性&#xff0c;比如猫科动物&#xff0c;它所拥有的属性&#xff08;参数&#xff09;有胡子、能伸缩的爪子、随光线缩放自如的瞳孔、夜视能力、优秀的弹跳力、萌等等。ROS节点中参数支持的数据类型有整型…

分治实现快速排序和归并排序

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 一.快速排序&#xff08;升序为例&#xff09; 思想&#xff1a;确定分界点x&#xff0c;将小于分界点的值放在分界点的左边&#xff0c;将大于分界定的值放在分界点的右边&#xff0c;再递归处理两边的左右区间。 步骤&am…

1、Cocos Creator 基础入门

目录 Cocos Creator 是什么&#xff1f; 语言支持 功能特性 工作流程 功能模块 相关游戏 参考 Cocos Creator 是什么&#xff1f; Cocos Creator 既是一款高效、轻量、免费开源的跨平台 2D&3D 图形引擎&#xff0c;也是一个实时 2D&3D 数字内容创作平台。拥有…

Java研学-SpringBoot(四)

六 SpringBoot 项目搭建 1 创建项目 spring2.X版本在2023年11月24日停止维护&#xff0c;而Spring3.X版本不支持JDK8&#xff0c;JDK11&#xff0c;最低支持JDK17&#xff0c;目前阿里云还是支持创建Spring2.X版本的项目 2 修改所需依赖版本 – pom <?xml version&quo…

从0开始打架基于VUE的前端项目

准备与版本 安装nodejs(v20.11.1)安装vue脚手架(@vue/cli 5.0.8) ,参考(https://cli.vuejs.org/zh/)vue版本(2.7.16),vue2的最后一个版本初始化项目 创建一个git项目(可以去gitee/github上创建),注意创建一个空项目创建项目vue create mvp-admin-vue-ui删除自己创建的gi…

如何制作Word模板并用Java导出自定义的内容

1前言 在做项目时会按照指定模板导出word文档,本文讲解分析需求后,制作word模板、修改模板内容,最终通过Java代码实现按照模板自定义内容的导出。 2制作word模板 2.1 新建word文档 新建word文档,根据需求进行编写模板内容,调整行间距和段落格式后将指定替换位置留空。…

50 基于 provide/inject 属性的模型视图不同步问题

前言 这是一个之前 2023年12月月底碰到的一个问题 这个问题还是 比较复杂, 呵呵 这个在当时 看来 我甚至觉得 我可能搞不定这个问题 但是 当时出现了一些 其他的可以临时解决这个问题的方式, 因此 当时就没有深究 然后 过了两天 重新复现了一下 问题, 重新看了一下 这个问题…

2023年第十四届蓝桥杯大赛软件类省赛C/C++研究生组真题(代码完整题解)

C题-翻转⭐ 标签:贪心 简述:如果 S 中存在子串 101 或者 010,就可以将其分别变为 111 和 000,操作可以无限重复。最少翻转多少次可以把 S 变成和 T 一样。 链接: 翻转 思路:要求步骤最少->S每个位置最多修改一次->从头开始遍历不匹配就翻转->翻转不了就-1 …

CVE-2023-38408漏洞修复 - 升级openssl和openssh

CVE-2023-38408 OpenSSH 代码问题漏洞修复 - 升级openssl和openssh ※ 重要说明&#xff1a; 1、升级后会导致无法用ssh远程登录&#xff0c;提示“Permission denied, please try again.” 2、解决方案请查看本章节【三、解决升级后无法用ssh远程登录】 目录 CVE-2023-38408 O…

集合(ArrayList,HashMap,HashSet)详解+ entrySet的应用

集合 例题引入——直线题意分析根据下面的参考代码&#xff0c;自己模仿的参考代码&#xff08;加一点点我的小tips&#xff09; 1.java集合引入2.为什么要使用集合&#xff1f;3.List、Set、Queue和Map的区别4.ListList——ArrayList&#xff08;&#xff01;&#xff01;实用…

武汉星起航:跨境电商获各大企业鼎力支持,共筑繁荣生态

随着全球化和数字化的深入发展&#xff0c;跨境电商行业逐渐成为连接国内外市场的重要桥梁。在这一进程中&#xff0c;各大企业纷纷加大对跨境电商行业的支持力度&#xff0c;通过投资、合作与创新&#xff0c;共同推动行业的繁荣与发展。武汉星起航将探讨各大企业对跨境电商行…

图片标注编辑平台搭建系列教程(6)——fabric渲染原理

原理 fabric的渲染步骤大致如下&#xff1a; 渲染前都设置背景图然后调用ctx.save()&#xff0c;存储画布的绘制状态参数然后调用每个object自身的渲染方法最后调用ctx.restore()&#xff0c;恢复画布的保存状态后处理&#xff0c;例如控制框的渲染等 值得注意的是&#xff0…

Verilog语法之case语句学习

case分支语句是一种实现多路分支控制的分支语句。与使用if-else条件分支语句相比&#xff0c;采用case分支语句来实现多路控制会变得更加的方便直观。 case分支语句通常用于对微处理器指令译码功能的描述以及对有限状态机的描述。Case分支语句有“case”、“casez”、“casex”…

使用pdf表单域填充pdf内容

需要引用如下包 <dependency><groupId>com.itextpdf</groupId><artifactId>itext-core</artifactId><version>8.0.3</version><type>pom</type></dependency>1、预先准备一个pdf模板&#xff0c;并在指定位置添加…

C/C++语言实现简易通讯录 [含文件操作,循环双链表]

文章目录 C/C语言实现简易通讯录概要基本功能运行截图展示主要代码展示 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alaskan Malamute &#x1f4dc; 博主的代码仓库主页 [ Gitee ]&#xff1a;ryanala [GitHub]&#xff1a; Ryan-Ala C/C语言实现简易通讯录 ⚠⚠⚠ …

Android 开发投屏软件

一、背景 作为Android开发总会有给他人share自己APP情况&#xff0c;一般在线会议投屏&#xff0c;总是需要在手机上安装对应会议软件特别麻烦~ 二、投屏 Android Studio已经自带了投屏能力&#xff0c;可以在电脑端直接控制手机&#xff0c;同步起来非常方便简单 打开步骤 …

【Kubernetes】K8s 中的 Pod 驱逐

K8s 中的 Pod 驱逐 1.Pod 被驱逐的原因&#xff1a;抢占和节点压力2.抢占式驱逐2.1 Pod 调度2.1.1 过滤2.1.2 计分 2.2 Pod 优先级2.3 优先级示例 3.节点压力驱逐3.1 服务质量等级3.1.1 Guaranteed3.1.2 Burstable3.1.3 BestEffort 4.其他类型的驱逐4.1 API 发起的驱逐&#xf…