0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用OpenVINO™ ElectronJS中创建桌面应用程序

英特尔物联网 来源:英特尔物联网 2024-11-25 11:35 次阅读

最近,我完成了一个 demo 演示,展示了 OpenVINO 在 Node.js 框架中的强大功能。得益于与 Electron.js 的集成,该演示不仅能够高效地执行神经网络推理,还提供了交互式的用户体验。

1

应用程序概览:一种简单的背景虚化方法

这个演示展示了如何在 Node.js 环境中使用 OpenVINO 工具包实现背景虚化,并通过 Electron.js 创建的直观桌面界面进行呈现。启动应用程序后,您会看到一个带有黑色占位符的界面。要激活摄像头,只需从检测到的设备列表中选择您喜欢的视频源并点击“开始”。

edbc63e0-a8b8-11ef-93f3-92fbcf53809c.png

完成此步骤后,您应该会在界面中的框内看到来自摄像头的实时视频流。

最初,您的画面将显示为未经过任何虚化处理的原始图像。要启用背景虚化功能,请通过指定的切换开关打开推理模式。该应用还允许您选择推理设备,可以在操作前或操作过程中进行设置。当您在会话中首次选择设备时,可能会出现短暂的延迟,因为模型需要进行编译。

在摄像头画面上方,您会看到一个推理时间显示器,显示最近50帧的平均推理时间。同时,还会显示每秒处理(或推理)的帧数,让您了解性能表现。

在应用运行期间,您可以随时停止摄像头或推理,切换视频源,或更改推理设备。

2

项目架构

完整代码可以在 OpenVINO Build & Deploy 仓库中找到。该 Electron 应用项目分为几个关键部分:

GitHub - openvinotoolkit/openvino_build_deploy: Pre-built components and code samples to help you build and deploy production-grade AI applications with the OpenVINO Toolkit from Intel

界面(Interface):

包括定义界面视觉效果的 HTML 和 CSS 文件,以及控制功能的 renderer.js 文件。

OpenVINO 任务(OpenVINO Jobs):

后端组件,位于 ov-jobs.js 文件中,包含推理、前处理、后处理和背景虚化的相关函数。

主程序(Main):

main.js 文件负责启动应用程序,设置必要参数,并处理中断等操作。

预加载(Preload):

preload.js 文件作为主程序与界面组件之间的桥梁,启用后端功能并处理用户触发的中断。

Node 模块(Node Modules):

程序所需的外部库和模块列在 package.json 文件中,同时包含其他必要的开发信息。要安装这些模块,只需在主目录运行以下命令:

npm install

保持清晰的项目架构至关重要,因为 OpenVINO 的 Node.js 库只能在后端运行。如果将其导入到界面层会导致错误。因此,最佳实践是将 OpenVINO 的导入限制在 ov-jobs.js 文件中。

3

它是如何工作的?

背景虚化功能使用了一个来自 TensorFlow 的分割模型,名为 “TensorFlow_Lite_Frontend_IR”,该模型已被转换为 OpenVINO 的 IR 格式。此模型要求输入尺寸为 1x3x256x256,因此在预处理步骤中,需要将图像调整为正方形(无需填充)。如果图像不是 RGB 格式,还需要将其颜色表示转换为 RGB 格式。

const sharp = require('sharp');
// originalImg is a sharp object.
async function preprocess(originalImg) {
  const inputSize = { w: 256, h: 256 };
  const inputImg = await originalImg
    .resize(inputSize.w, inputSize.h, { fit: 'fill' })
    .removeAlpha() // converting RGBA to RGB
    .raw()
    .toBuffer();
  const resizedImageData = new Uint8ClampedArray(inputImg.buffer);
  const tensorData = Float32Array.from(resizedImageData, x => x / 255);
  const shape = [1, inputSize.w, inputSize.h, 3];
  return new ov.Tensor(ov.element.f32, shape, tensorData);

该模型作为分类器工作,将图像中的每个像素分配到六个类别之一,其中类别 0 代表背景。在推理后,输出会经过后处理生成一个掩码,其中 0 表示背景(需要进行虚化),1 表示其他元素(需要保持清晰)。随后,该掩码会被调整为与原始图像尺寸匹配。

程序运行时采用两个主要线程:一个线程从摄像头捕获帧,根据掩码对背景进行虚化处理,并将处理后的结果显示在屏幕上。另一个线程“借用”一帧图像,运行推理以更新掩码,确保摄像头的画面保持流畅,即使某些设备上的推理需要较长时间。

4

JavaScript 中

使用 OpenVINO 的基本功能

发现可用来进行推理的设备:

const { addon: ov } = require('openvino-node');
const core = new ov.Core();
const devices = core.getAvailableDevices();

读入和编译模型:

const { addon: ov } = require('openvino-node');
const core = new ov.Core();
const modelPath = "path/to/your/model";
const model = await core.readModel(modelPath);
const device = "AUTO"; // or "GPU", "CPU" and others
const compiledModel = await core.compileModel(model, device);

运行编译后的模型:

// have compiledModel and inputTensor prepared
let inferRequest = compiledModel.createInferRequest();
inferRequest.setInputTensor(inputTensor);
inferRequest.infer() // inference
const outputLayer = compiledModel.outputs[0]; // only one output in this scenario
const resultTensor = inferRequest.getTensor(outputLayer); // your inference result

虚化步骤:

这是最简单的虚化图像的方式:

捕获一帧图像
从摄像头捕获当前帧。

复制并虚化图像
创建原始图像的副本,使用 sharp.blur() 对整个副本进行虚化处理(替代方案:OpenCV 或卷积操作)。

获取分割模型生成的掩码
在独立线程中运行分割模型,获取当前帧的掩码。

应用掩码到虚化图像
将虚化图像的所有像素值与掩码相乘,保留需要虚化的区域。

生成“反掩码”
计算掩码的反值(即 1 - mask),生成“非虚化区域掩码”。

应用“反掩码”到原始图像
将原始图像的像素值与“反掩码”相乘,保留需要保持清晰的区域。

融合两张图像
将虚化后的图像和清晰区域的图像进行融合,生成最终图像。

在最终的应用程序代码中,多个操作被整合在一起,充分利用了 Sharp 库的功能。以下是使用 Sharp 实现的方法:

1.根据掩码裁剪原始图像:

const sharp = require('sharp');
const person = await sharp(outputMask, {
    raw: {
      channels: 3,
      width: inputSize.w,
      height: inputSize.h,
    }
  })
    .resize(width, height, { fit: 'fill' })
    .unflatten()
    .composite([{
      input: image.data,
      raw: {
        channels: 4,
        width,
        height,
      },
      blend: 'in',
    }])
    .toBuffer();

2.对副本进行虚化处理,并将其与裁剪后的原始图像合并(复合):

const blurSize = Math.floor(widthOfImage * 0.01)
const blurredImage = await sharp(imageToBlur.data, {
  raw: { channels: 4, width, height }, // back to RGBA
})
  .blur(blurSize)
  .composite([{
    input: person,
    raw: { channels: 4, width, height },
    blend: 'atop'
  }])
  .raw()
  .toBuffer();

5

虚化面临的挑战

图像虚化是一项耗时的操作,对性能影响较大,尤其是当它是图像显示线程的一部分时,这直接关系到用户体验。没有人希望视频流出现卡顿。


一种优化方法是在一开始就将图像调整为最终显示的大小。较小的图像处理速度更快,从而提高性能。

起初,我们尝试使用 OpenCV 的虚化功能(通过 opencv-wasm 模块)。然而事实证明,其速度太慢,甚至比模型推理还慢,这促使我们寻找替代方案。

我们曾设想创建一个专门用于虚化的轻量化模型。该模型以图像帧和掩码作为输入,执行“虚化过程”部分描述的数学操作,并通过深度卷积(Depthwise Convolution)实现虚化。我们使用 TensorFlow 构建了这个模型,并将其转换为 OpenVINO 格式。

重要说明:OpenVINO 从 2024.4 版本开始度卷积操作。

尽管这种方法具有潜力,但由于深度卷积速度较慢且优化不足,最终被我们放弃。

最终,我们发现 Sharp 库在此操作中表现最佳,因此将其作为项目中的解决方案。

6

总结

如果遵循以下关键指南,使用 Electron.js 和 OpenVINO 创建桌面应用程序是非常简单的:

1.前后端功能分离:

确保将后端功能与前端功能分开,并记住 OpenVINO 只能在后端使用。

2.JavaScript API 的局限性:

并非所有 Python 中可用的 OpenVINO 方法都已在 JavaScript 中实现。然而,当前的 API 已足以完成大多数任务。

3.阅读文档:

许多常见问题的答案都可以在文档中找到。参考 OpenVINO Node.js API 文档以获取更多信息。

4.检查库兼容性:

某些 JavaScript 库可能无法很好地与 Electron 配合使用。在这些情况下,您可能需要寻找替代版本或定制分支。

别忘了亲自体验一下 "Hide Your Mess Behind" 应用程序!您可以从代码仓库运行该应用程序,也可以下载适用于 Windows(exe)或 Linux(deb、rpm)的可执行版本。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 应用程序
    +关注

    关注

    37

    文章

    3245

    浏览量

    57615
  • OpenVINO
    +关注

    关注

    0

    文章

    90

    浏览量

    182

原文标题:开发者实战|如何使用 OpenVINO™ 在 ElectronJS 中创建桌面应用程序

文章出处:【微信号:英特尔物联网,微信公众号:英特尔物联网】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    桌面应用程序可以使用广播255.255.255.255吗

    应用程序会侦听并发送一个请求(使用广播)来改变IP到相同的网络范围。例如,这是很好的工作,但我的疑问是:在桌面应用程序,我可以使用广播255.255.255.255,或者我应该
    发表于 02-26 15:27

    如何创建 UEFI LCD与运行 LCD 应用程序(2)

    创建 UEFI LCD 应用程序、运行 LCD 应用程序(第二部分)
    的头像 发表于 06-22 01:50 3039次阅读

    如何创建 UEFI LCD与运行 LCD 应用程序(1)

    创建 UEFI LCD 应用程序、运行 LCD 应用程序(第一部分)
    的头像 发表于 06-22 04:24 3382次阅读

    使用OpenCL应用程序的英特尔SDK创建代码

    使用适用于OpenCL应用程序的英特尔SDK创建,构建和调试OpenCL代码
    的头像 发表于 10-30 06:26 3461次阅读

    如何使用Xilinx SDK创建Linux应用程序,并进行开发和调试

    了解如何使用Xilinx SDK创建Linux应用程序。 我们还将重点介绍和演示支持Linux应用程序开发和调试的不同方面的SDK功能。 整个过程快速而简单。
    的头像 发表于 11-20 07:03 1.1w次阅读

    何使用Xilinx软件开发套件XSDK创建简单的应用程序

    了解如何使用Xilinx软件开发套件(XSDK)应用程序模板创建简单的应用程序。 本视频将引导您完成创建“Hello,World!”,
    的头像 发表于 11-26 06:59 3916次阅读

    怎样创建树莓派上的Web应用程序 并使用Flask Web Framework控制伺服电机

    在这篇文章,您将学习如何创建Raspberry Pi上的Web应用程序,使用Flask Web Framework控制伺服电机,以创建Web应用程
    的头像 发表于 07-26 15:27 6575次阅读

    如何创建Windows 10 Arduino应用程序

    Microsoft将全力投入Windows 10,最终实现了拥有可跨平台运行的应用程序的梦想。结合对Arduino的官方支持,您可以使用一个功能强大的新工具:能够轻松创建具有与现实世界硬件连接的通用Windows应用程序的功能。
    的头像 发表于 12-03 08:53 2693次阅读

    Fliqlo桌面时钟软件应用程序免费下载

    本文档的主要内容详细介绍的是Fliqlo桌面时钟软件应用程序免费下载
    发表于 03-30 08:00 0次下载

    创建一个简单的人脸识别桌面应用程序

    错误也是常有的。 本文是基于虹软人脸识别SDK 3.0Windows(X86),C/C++的demo,封装后输出的一个简单的可直接体验的桌面应用程序,初次接触者可以快速体验人脸识别功能,便于做算法选型、调研及上级汇报! 2.应用程序
    的头像 发表于 09-15 17:10 1875次阅读

    用于创建新固件应用程序的软件工具Keil IDE

    用于创建新固件应用程序的软件工具Keil IDE
    发表于 06-06 08:09 4次下载
    用于<b class='flag-5'>创建</b>新固件<b class='flag-5'>应用程序</b>的软件工具Keil IDE

    【从0开始创建AWTK应用程序创建应用程序并在模拟器运行

    AWTK是基于C语言开发的跨平台GUI框架。本系列文章介绍如何从0开始创建AWTK应用程序,包括搭建开发调试环境、使用AWTK创建Hello工程并在模拟器上运行、将AWTK应用程序移植
    的头像 发表于 12-01 08:24 471次阅读
    【从0开始<b class='flag-5'>创建</b>AWTK<b class='flag-5'>应用程序</b>】<b class='flag-5'>创建</b><b class='flag-5'>应用程序</b>并在模拟器运行

    如何快速下载OpenVINO Notebooks的AI大模型

    OpenVINO Notebooks是Jupyter Notebook形式的OpenVINO范例程序大集合,方便开发者快速学习并掌握OpenVINO推理
    的头像 发表于 12-12 14:40 1082次阅读
    如何快速下载<b class='flag-5'>OpenVINO</b> Notebooks<b class='flag-5'>中</b>的AI大模型

    OpenAI推出ChatGPT桌面应用程序

    OpenAI 近日宣布,备受期待的 ChatGPT 桌面应用程序现已正式发布。在官方公告,OpenAI 表示他们首先会将这款应用提供给 Plus 用户群体,并特别针对 macOS 系统推出。这是该公司为了满足用户对更便捷、更
    的头像 发表于 05-14 11:51 988次阅读

    使用OpenVINO GenAI API在C++构建AI应用程序

    许多桌面应用程序是使用 C++ 开发的,而将生成式AI(GenAI)功能集成到这些应用程序可能会很具有挑战性,尤其是因为使用像 Hugging Face 这样的 Python 库的复
    的头像 发表于 10-12 09:36 316次阅读
    使用<b class='flag-5'>OpenVINO</b> GenAI API在C++<b class='flag-5'>中</b>构建AI<b class='flag-5'>应用程序</b>