爱智EdgerOS之深入解析AI图像引擎如何实现AI视觉开发

一、前言

  • AI 视觉是为了让计算机利用摄像机来替代人眼对目标进行识别,跟踪并进一步完成一些更加复杂的图像处理。这一领域的学术研究已经存在了很长时间,但直到 20 世纪 70 年代后期,当计算机的性能提高到足以处理图片这样大规模的数据时,计算机视觉才得到了正式的关注和发展。
  • 现在 AI 视觉已经在我们的生活中无处不在,从日常使用的二维码到人脸识别直至更专业的病理分析。AI 视觉的应用所渗透到的领域远比我们想象的更加广泛。虽然 AI 视觉的应用已经随处可见,但如果想要自己去开发一套属于自己的 AI 视觉应用,对于一个非专业领域的开发者还是非常复杂的,单从最基础的算法训练就要消耗掉大量的精力与时间。
  • EdgerOS 系统则内置了多种不同方向的 AI 引擎,使开发者可以实现快速实现 AI 视觉领域的开发,极大的降低了开发周期。开发者可以根据自己的需求对不同 AI 引擎进行组合达到自己想要的业务实现。本文将带领大家一起了解 EdgerOS 中常用的两款 AI 引擎。

二、FaceNN

  • FaceNN 是 EdgerOS 所提供的一个针对人脸识别的 AI 处理引擎,它可以从视频流或者图片中捕捉到人脸的具体位置,还可以根据人脸的特征来分析出对应人物的特征信息如:年龄、性别、情感等一些具体信息。
  • FaceNN 引擎封装在 “facenn” 模块中,可以通过以下方式来导入:
const facenn= require('facenn');
  • FaceNN 引擎提供了极简的接口,这使得开发者可以更加快速的实现关于人脸的 AI 处理,同时也降低了巨大的学习成本。
  • 首先需要明确一下被识别的图像格式,目前 FaceNN 引擎支持如下格式:
类型说明
facenn.PIX FMT RGB24RGB24 pixel format
facenn.PIX FMT BGR2RGB24BGR24 to RBG24 pixel format
facenn.PIXFMTGRAY2RGB24Grayscale to RGB24 pixel format
facenn.PIX FMT RGBA2RGB24RGBA to RGB24 pixel format
  • facenn.detect(videoBuf, attribute[, quick])
    • attribute {Object} 图像格式
      • width {Integer} 图像宽度
      • height {Integer} 图像高度
      • pixelFormat {Integer} 图像格式
    • quick {Boolean} 是否启用快速模式
  • 返回信息:
    • score {Number} 人脸的覆盖率
    • x0 {Integer} 左上角 x 的位置
    • y0 {Integer} 左上角 y 的位置
    • x1 {Integer} 右下角 x 的位置
    • y1 {Integer} 右下角 y 的位置
    • area {Number} Area,非快速模式
    • regreCoord {Array} RegreCoord,非快速模式
    • landmark {Array} Landmark,非快速模式
  • facenn.detect 可以识别出一帧图像数据中的人脸个数以及人脸所在图像中的位置。
  • facenn.feature(videoBuf, attribute, faceInfo[, extra])
    • videoBuf {Buffer} 图像格式
    • attribute {Object} 图像属性
      • width {Integer} 图像宽度
      • height {Integer} 图像高度
      • pixelFormat {Integer} 图像格式
    • extra {Object} 需要扩展的人脸信息 default: undefined
  • 返回信息:
    • keys {Array} Face keys
    • male {Boolean} 性别, 需要在扩展中选择
    • age {Integer} Age, 需要在扩展中选择
    • emotion {String} Emotion, 需要在扩展中选择
    • emotion 可分辨情绪包括: angry,disgust,fear,happy,sad,surprise,neutral
    • live {Number} 存活率,需要在扩展中选择
  • facenn.feature 可以识别出一张人像的具体信息,例如性别,情绪年龄等。
  • facenn.compare(faceKeys1, faceKeys2)
    • faceKey1 {Object} Face keys 1
    • faceKey2 {Object} Face keys 2
  • 返回信息:
    • 相似值 0.0 ~ 1.0
    • facenn.compare 可以比对出两张人脸信息的相似值。
  • 接下来用一下两张图片来尝试使用 FaceNN 引擎,读取其中的特征信息:

在这里插入图片描述
在这里插入图片描述

const imagecodec = require('imagecodec'); // 图片解析模块
const facenn = require('facenn'); function facennHandel(imagePath, imagePath2) {const image1 = imagecodec.decode(imagePath, imagecodec.COMPONENTS_RGB)const imageInfo1 = imagecodec.info(imagePath)const videoAttrFacenn = { width: imageInfo1.width, height: imageInfo1.height, pixelFormat: facenn.PIX_FMT_RGB24 }const faceInfos = facenn.detect(image1.buffer, videoAttrFacenn);const facennFeature = facenn.feature(image1.buffer, videoAttrFacenn, faceInfos[0], {male: true,age: true,emotion: true,live: true})console.log(`image1.png  male:${facennFeature.male} age:${facennFeature.age} emotion:${facennFeature.emotion} live:${facennFeature.live}`)const image2 = imagecodec.decode(imagePath2, imagecodec.COMPONENTS_RGB)const imageInfo2 = imagecodec.info(imagePath2)const videoAttrFacenn2 = { width: imageInfo2.width, height: imageInfo2.height, pixelFormat: facenn.PIX_FMT_RGB24 }const faceInfos2 = facenn.detect(image2.buffer, videoAttrFacenn2);const facennFeature2 = facenn.feature(image2.buffer, videoAttrFacenn2, faceInfos2[0], {male: true,age: true,emotion: true,live: true})console.log(`image2.png  male:${facennFeature2.male} age:${facennFeature2.age} emotion:${facennFeature2.emotion} live:${facennFeature2.live}`)const compareNum = facenn.compare(facennFeature.keys, facennFeature2.keys)console.log(compareNum)
}facennHandel('/image/image1.png', '/image/image2.png')// 输出如下:
// [JSRE-CON]image1.png  male:false age:21 emotion:neutral live:0.9843575954437256
// [JSRE-CON]image2.png  male:true age:58 emotion:sad live:0.33667701482772827
// [JSRE-CON]-0.1453045904636383

三、ThingNN

  • ThingNN 是 EdgerOS 可以从视频流或者图片中捕捉到具体事物,分别标记事务所在图片中的具体位置。
  • ThingNN 引擎封装在 “thingnn” 模块中,可以通过以下方式来导入:
const facenn= require('thingnn');
  • 同样也需要明确一下被识别的图像格式,目前 ThingNN 引擎支持如下格式:
类型说明
thingnn.PIX FMT_ RGB24RGB24 pixel format
thingnn.PIX_FMT_BGR2RGB24BGR24 to RBG24 pixel format
thingnn.PIX FMT GRAY2RGB24Grayscale to RGB24 pixel format
thingnn.PIX FMT RGBA2RGB24RGBA to RGB24 pixel format
  • 接下来看看 ThingNN 接口提供了那些接口:
  • thingnn.detect(videoBuf, attribute)
    • videoBuf {Buffer} 图像格式
    • attribute {Object} 图像属性
    • width {Integer} 图像宽度
    • height {Integer} 图像高度
    • pixelFormat {Integer} 图像格式
  • 返回信息:
    • className{Array} Face keys
    • prob{Boolean} 性别, 需要在扩展中选择
    • x0 {Integer} 左上角 x 的位置
    • y0 {Integer} 左上角 y 的位置
    • x1 {Integer} 右下角 x 的位置
    • y1 {Integer} 右下角 y 的位置
  • 目前 ThingNN 模块所支持可识别的类型都有:
background, aeroplane, bicycle, bird, boat,bottle, bus, car, cat, chair,cow, diningtable, dog, horse,motorbike,person, pottedplant,sheep, sofa, train, tvmonitor
  • thingnn.detect 可以获取到图片中事物的类别以及所在图像中的位置。
  • thingnn.identify(videoBuf, attribute, thingInfo)
    • videoBuf {Buffer} 图像格式
    • attribute {Object} 图像属性
    • width {Integer} 图像宽度
    • height {Integer} 图像高度
    • pixelFormat {Integer} 图像格式
    • thingInfo {Object} 事务对象
  • 返回信息:具体事物的名称,thingnn.identify 可以获取到具体 thinginfo 的类型名称。
  • 以下图为例子作为演示:

在这里插入图片描述

const imagecodec = require('imagecodec'); // 图片解析模块
const facenn = require('facenn'); function licplatennHandel(imagePath) {
const imageInfo = imagecodec.info(imagePath)
const imageBuf= imagecodec.decode(imagePath, imagecodec.COMPONENTS_RGB).buffer
let videoAttrThingnn = { width: imageInfo.width, height: imageInfo.height, pixelFormat: thingnn.PIX_FMT_BGR24 }const thingInfos = thingnn.detect(imageBuf, videoAttrThingnn);thingInfos.forEach((thingInfo, index) => {const thingName = thingnn.identify(imageBuf, videoAttrThingnn, thingInfo);console.log(index,thingInfo.className, thingName)})
}licplatennHandel('/image/dog.png')// 输出如下:
// [JSRE-CON]0 dog Labrador retriever

四、ImageCodec

  • FaceNN 模块在单独使用时是处理视频流中的人脸信息的,现在假设我们的场景是一个智能门锁,首先需要录入人脸信息,添加为合法的开锁用户,门锁摄像头再捕获视频流检测出人脸信息进行核对,校验通过则打开门锁。在录入人脸信息的时候,需要将多张人脸照片处理成流信息提供给 FanceNN 模块进行解析,ImageCodec 模块刚好就可以胜任此工作。
  • ImageCodec 模块提供了对多种图像格式进行编码和解码方法,包括:PNG,JPG,BMP,TGA,HDR,接下来具体看一下,如何通过 ImageCodec 处理图片数据。
const imagecodec = require('imagecodec')

① 区分带通道的图片

  • 在对图片进行解码的时候需要区别处理带通道的 PNG 图片,ImageCodec 模块上的 decode 方法支持传入第二个可选参数:
    • imagecodec.decode(path[, opt]):
const image = imagecodec.decode('./test.png', {components: imagecodec.COMPONENTS_RGB_ALPHA})
  • opt 的配置选项 components 可以指定以下值来区别处理不同格式的图片:
定义描述
imagecodec.COMPONENTS_DEFAULT0使用图片的默认值
imagecodec.COMPONENTS_GREY1单字节灰度图像
imagecodec.COMPONENTS_GREY_ALPHA2带有 Alpha 通道的灰度图像
imagecodec.COMPONENTS_RGB3三字节 RGB 图像
imagecodec.COMPONENTS_RGB_ALPHA4带有 Alpha 通道的 RGB 图像
  • 如何判断一个图片的格式,我们知道计算机实际并不是根据后缀来判断文件类型的,事实上,有个东西叫魔法数字(Magic Number),它是某一类型的文件的头一个或几个字节的内容,可以根据这个来判断传入的图片文件是什么类型的:
const fs = require('fs')
const imagecodec = require('imagecodec')
const imageBuffer = fs.readFile('./human.jpg')let type = ''
const arr = (new Uint8Array(picture)).subarray(0, 4)
const headerString = arr.reduce((acc, cur) => acc+cur.toString(16), '')
switch (headerString) {case "89504e47":type = "png";breakcase "47494638":type = "gif";breakcase "ffd8ffe0":case "ffd8ffe1":case "ffd8ffe2":type = "jpg"breakdefault:console.log('[mime-type] not png/gif/jpg.')break
}
  • 将图片文件的前 4 个字节(4 个字节的长度已经足够判断出图片的类型了)拿出来进行判断,一般拍照上传的照片是 JPG 或 PNG,所以这里只需要判断出图片是否是带有 ALPHA 通道的图片即可。

② decode 方法解析图片文件

  • 上面判断出图片类型之后,就可以通过 decode 方法解码图片文件:
const bitmap = imagecodec.decode(picture, {components: type === 'png' ? imagecodec.COMPONENTS_RGB_ALPHA : imagecodec.COMPONENTS_RGB
})
  • decode解析得到的 bitmap 为一个图像像素对象,它包含 width,height,components,buffer 4个属性,也正是 FaceNN 所需要的内容。

③ 解析图片中的人脸信息

  • 这里跟 AI 识别的内容基本一致:
const facenn = require('facenn')const faces = facenn.detect(bitmap.buffer, {width: bitmap.width,height: bitmap.height,pixelFormat: type === 'png' ? facenn.PIX_FMT_RGBA2RGB24 : facenn.PIX_FMT_RGB24
}, true)
  • 此时得到的 faces 内容就是识别之后的人脸特征信息,从图片中获取面部信息的功能就完成。

④ 封装成包

  • 这个功能已经封装成一个 jsre 包上传到了 npm 仓库,可以通过以下方式进行安装和使用:
npm install @edgeros/ofiiconst getFaceFeature = require('@edgeros/ofii')
const imageBuffer = fs.readFile('./hunman.png')
const keys = getFaceFeature(imageBuffer)
// 如果没有检测到人脸信息则返回 []
  • 在不同的场景中我们需要对图片进行编码解码,来配合完成更加复杂的功能和服务。EdgerOS 在网络应用,人工智能等场景提供了丰富的接口,能够极大简化开发流程。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【c语言指针详解】复杂数据结构的指针用法

目录 一、动态内存分配 1.1 使用malloc和free函数进行内存的动态分配和释放 1.2 内存泄漏和野指针的概念和解决方法 二、复杂数据结构的指针用法 2.1 结构体指针和成员访问操作符 2.2 指针数组和指向指针的指针 2.2.1 指针数组 2.2.2 指向指针的指针 2.3 动态内存分配与结构体指…

Learning Memory-guided Normality for Anomaly Detection 论文阅读

Learning Memory-guided Normality for Anomaly Detection 摘要1.介绍2.相关工作3.方法3.1网络架构3.1.1 Encoder and decoder3.1.2 Memory 3.2. Training loss3.3. Abnormality score 4.实验5.总结总结&代码复现: 文章信息: 发表于:cvpr…

线程状态:深入理解多任务并发编程中的精髓

目录 引言 1. 线程状态概述 1.1 定义 1.2 线程状态图 2. 线程状态的转换 2.1 新建到就绪 2.2 就绪到运行 2.3 运行到阻塞 2.4 运行到等待和超时等待 2.5 运行到终止 3. 实际编程中的线程状态管理 3.1 合理使用wait()和notify() 3.2 谨慎处理阻塞状态 3.3 使用线程…

力扣面试经典150题——Unix简化路径

https://leetcode.cn/problems/simplify-path/description/?envTypestudy-plan-v2&envIdtop-interview-150 思路:将串以/分割,判断字符串是…/./其他,进行入栈和出栈,最后留下的就是结果,拼装一下就好了。 三个…

设计模式之结构型模式(适配器、桥接、组合、享元、装饰者、外观、代理)

文章目录 一、结构型设计模式二、适配器模式三、桥接模式四、组合模式五、享元模式六、装饰者模式七、外观模式八、代理设计模式 一、结构型设计模式 这篇文章我们来讲解下结构型设计模式,结构型设计模式,主要处理类或对象的组合关系,为如何…

前后端数据传输格式(上)

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 作为后端,写…

Leetcode—198.打家劫舍【中等】

2023每日刷题(五十二) Leetcode—198.打家劫舍 算法思想 具体思路 首先,我们从上面的题目描述中抽象出题意。 ● 从一个非负整数数组中找到一个子序列,并且该子序列的和最大 ● 子序列中每个数的位置不能够相邻。举例来讲&…

【C语言】动态内存管理(C语言的难点与精华,数据结构的前置知识,你真的掌握了吗?)

文章目录 引言一、为什么要动态内存分配二、动态内存分配的相关函数2.1 malloc2.2 free2.3 calloc2.4 realloc 三、常见的动态内存的错误3.1 对NULL指针的解引用3.2 对动态内存越界访问3.3 对非动态内存释放3.4 对动态内存部分释放3.5 对动态内存多次释放3.6 未对动态内存释放&…

Java-JDBC操作MySQL

Java-JDBC操作MySQL 文章目录 Java-JDBC操作MySQL一、Java-JDBC-MySQL的关系二、创建连接三、登录MySQL四、操作数据库1、返回型操作2、无返回型操作 练习题目及完整代码 一、Java-JDBC-MySQL的关系 #mermaid-svg-B7qjXrosQaCOwRos {font-family:"trebuchet ms",verd…

邮政快递查询,邮政快递单号查询,按物流更新量筛选出需要的单号

批量查询邮政快递单号的物流信息,按物流更新量将需要的单号筛选出来。 所需工具: 一个【快递批量查询高手】软件 邮政快递单号若干 操作步骤: 步骤1:运行【快递批量查询高手】软件,并登录 步骤2:点击主界…

PHP短信接口防刷防轰炸多重解决方案三(可正式使用)

短信接口盗刷轰炸:指的是黑客利用非法手段获取短信接口的访问权限,然后使用该接口发送大量垃圾短信给目标用户 短信验证码轰炸解决方案一(验证码类解决)-CSDN博客 短信验证码轰炸解决方案二(防止海外ip、限制ip、限制手机号次数解决)-CSDN博客 PHP短信…

《opencv实用探索·八》图像模糊之均值滤波、高斯滤波的简单理解

1、前言 什么是噪声? 该像素与周围像素的差别非常大,导致从视觉上就能看出该像素无法与周围像素组成可识别的图像信息,降低了整个图像的质量。这种“格格不入”的像素就被称为图像的噪声。如果图像中的噪声都是随机的纯黑像素或者纯白像素&am…

Fiddler抓包模拟器(雷电模拟器)

Fiddler设置 List item 打开fiddler,的options 点击OK,重启fiddler 模拟器 更改网络设置 IP可以在电脑上终端上查看 然后在模拟器浏览器中输入IP:端口 安装证书

[二分查找双指针]LeetCode881: 救生艇

救生艇 作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本文涉及的基础知识点 二分查找算法合集 题目 给定数组 people 。people[i]表示第 i 个人的体重 ,船的数量不限,每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&am…

[足式机器人]Part2 Dr. CAN学习笔记-数学基础Ch0-5Laplace Transform of Convolution卷积的拉普拉斯变换

本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-数学基础Ch0-5Laplace Transform of Convolution卷积的拉普拉斯变换 Laplace Transform : X ( s ) L [ x ( t ) ] ∫ 0 ∞ x ( t ) e − s t d t X\left( s \right) \mathcal{L} \left[ x\lef…

QT作业2

使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为…

【Flink系列三】数据流图和任务链计算方式

上文介绍了如何计算并行度和slot的数量,本文介绍Flink代码提交后,如何生成计算的DAG数据流图。 程序和数据流图 所有的Flink程序都是由三部分组成的:Source、Transformation和Sink。Source负责读取数据源,Transformation利用各种…

Linux各目录结构说明

文章目录 目录说明源码放哪里?拓展:Linux里面安装软件是装在home目录还是opt目录还是/usr/local好? bin boot dev etc home lib lib64 lostfound media mnt opt proc root run sbin srv sys tmp usr var 目录说明 bin 存放二进制可执行文件&…

《Spring Cloud Alibaba 从入门到实战》分布式配置

分布式配置 1、简介 Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。 Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案,在特殊的 bootstrap 阶段,…

2023.12.4 关于 Spring Boot 统一异常处理

目录 引言 统一异常处理 异常全部监测 引言 将异常处理逻辑集中到一个地方,可以避免在每个控制器或业务逻辑中都编写相似的异常处理代码,这降低了代码的冗余,提高了代码的可维护性统一的异常处理使得调试和维护变得更加容易,通…