亿琪软件-开源博客 - AI
type: channel
link: https://www.yiqisoft.cn/blogs/tag/AI/
items: 技术｜ONVIF 摄像头视频读取，YiEDGE 拉流，RV1126 实现推理
items: 技术｜在 RV1126 之上使用 rknn_toolkit_lite 和 eKuiper pipeline 进行图片识别推理
items: 技术｜RV1126 系统安装 Docker 及初始化运行环境
items: 技术｜RV1126 本地运行 rnkk-toolkit-lite，用 eKuiper 实现 python 视频 AI 推理
items: 技术｜RV1126 本地安装 rnkk-toolkit-lite，实现 python 实施 AI 推理
items: 白皮书｜YiEDGE-亿琪边缘计算软件
items: YiAI 人工智能算法-动物姿态识别
items: YiAI 人工智能算法路况测试视频
items: Cosine similarity 余弦相似性原理及其应用

技术｜ONVIF 摄像头视频读取，YiEDGE 拉流，RV1126 实现推理
type: item
date: 2023-02-17T15:41:00+00:00
description: 目录 ONVIF 协议 YiEDGE 边缘计算框架 管理 ONVIF 摄像头 同步到 Message Bus YiEVAS 系统 eKuiper 作为 pipeline 引擎 ONVIF 通告获取 stream rule-onvif-camera 拉流，抓帧，推理 拉流 抓帧 推理 结果输出 创建被管理摄像头 在边缘计算视频分析方面，ONVIF 协议实现了摄像头管理，YiEDGE 实现了拉流和图片输出，YiEVAS 模块 Pyairknn 实现推理。 ONVIF 协议 开放型网络视频接口论坛（英语：Open Network Video Interface Forum，简称ONVIF），是一个国际开放型网络视频产品标准网络接口开发论坛. IPC 摄像头必须支持 ONVIF 协议； 实现自动多摄像头并行处理性能要求； ONVIF Device Manager，用这个软件连接摄像头查看。 YiEDGE 边缘计算框架 YiEDGE 框架基于 EdgeX 框架做了深层次定制，实现了更加自动化的功能，增加了南向设备接口协议，增加了北向云平台接口协议。 管理 ONVIF 摄像头 采用 device onvif camera 设备层协议，对接各种支持 ONVIF 的摄像头设备； 定期探测网络中的 IPC； 轮训摄像头状态，获取 streamuri 地址；创建被管理摄像头 这里以 HK 摄像头为例，10s 轮训一次。 { "apiVersion": "v2", "statusCode": 200, "device": { "created": 1676646639846, "modified": 1676646710817, "id": "9a9a3276-cf19-4e01-908c-801a520ba5be", "name": "IPC-HK", "adminState": "UNLOCKED", "operatingState": "UP", "labels": [ "" ], "serviceName": "device-onvif-camera", "profileName": "onvif-camera", "autoEvents": [ { "interval": "10s", "onChange": false, "sourceName": "StreamUri" } ], "protocols": { "Onvif": { "Address": "192.168.123.183", "DeviceStatus": "UpWithAuth", "FirmwareVersion": "V5.7.3 build 220315", "FriendlyName": "HIKVISION DS-IPC-T12HV3-IA", "HardwareId": "88", "LastSeen": "Fri Feb 17 15:11:50 UTC 2023", "MACAddress": "c0:6d:ed:eb:cb:59", "Manufacturer": "HIKVISION", "Model": "DS-IPC-T12HV3-IA", "Port": "80", "SerialNumber": "DS-IPC-T12HV3-IA20220913AACHK56293791" } } } } streamUri 信息内容 [ { "id": "c88007b8-4316-451c-87b4-2dec7f1f540d", "origin": 1676646870752047000, "deviceName": "IPC-HK", "resourceName": "StreamUri", "profileName": "onvif-camera", "valueType": "Object", "value": "", "objectValue": { "MediaUri": { "InvalidAfterConnect": false, "InvalidAfterReboot": false, "Timeout": "PT60S", "Uri": "rtsp://192.168.123.183:554/Streaming/Channels/0?transportmode=unicast&profile=Profile_1" } } } ] 同步到 Message Bus 以上信息都会同步到数据总线； 可以自定义轮训时间； 筛选需要通告总线的 IPC； YiEVAS 系统 eKuiper 作为 pipeline 引擎 大概模式如下： |source输入->|rule规则引擎->|sink输出->| |:----|:----|:----| |onvi…

技术｜在 RV1126 之上使用 rknn_toolkit_lite 和 eKuiper pipeline 进行图片识别推理
type: item
date: 2023-02-17T14:20:00+00:00
description: 本文使用 Base64，OPENCV，Numpy 和 Image 组件进行数据读取转换。 图片格式 一般在边缘计算端进行推理，不会使用一张一张图片，而是采用视频流读帧的方式。 二进制文件格式 file_bytes = "binary file" // 初始化图片二进制 encoded = base64.decodebytes(file_bytes.encode("ascii")) // 转换成base64 img = Image.open(io.BytesIO(encoded)).resize((width, height)) // 打开图片 input_data = np.array(img) // 转换成 numpy image = cv2.cvtColor(input_data, cv2.COLOR_BGR2RGB) // OPENCV 读取图片 图片(二进制)-->base64-->Image-->numpy array-->opencv Base64 编码格式 如果是 Base64 格式输入，处理方法一样，但是，在输入流的地方，要注意 source 采用 json 编码。 // 代码通用 // 输入格式： {"image": "/9j/4AAQSk....X//2Q=="} 图片(json base64）-->Image-->numpy array-->opencv eKuiper source 读取源（输入输入） eKuiper 定义 source 唯一区别就是 format: binary/json，假设都是采用 mqtt broker 作为图片输入。 Binary 二进制格式 输入源定义： { "Name" : "binaryimage", "Options" : { "confKey" : "edgex_mqtt_broker", "datasource" : "image", "format" : "binary", "type" : "mqtt" }, "Statement" : null, "StreamFields" : null, "StreamType" : 0 } 输入图片示例代码, GOLANG，这里的 payload 直接是 ReadFile，二进制： package main import ( "fmt" "io/ioutil" "time" mqtt "github.com/eclipse/paho.mqtt.golang" ) func main() { const TOPIC = "binaryimage" images := []string{ "parrot.jpg", "owl.jpg", "out.jpg", // 其他你需要的图像 } opts := mqtt.NewClientOptions().AddBroker("tcp://192.168.123.184:1883") client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } for _, image := range images { fmt.Println("Publishing " + image) payload, err := ioutil.ReadFile(image) if err != nil { fmt.Println(err) continue } if token := client.Publish(TOPIC, 0, false, payload); token.Wait() && token.Error() != nil { fmt.Println(token.Error()) } else { fmt.Println("Published " + image) } time.Sleep(1 * time.Second) } client.Disconnect(0) } Json 格式 输入源定义： { "Name" : "jsonimage", "Options" : { "confKey" : "edgex_mqtt_broker", "datasource" : "image", "format" : "json", "type" : "mqtt" }, "Statement" : null, "StreamFields" : null, "StreamType" : 0 } 输入图片为 base64 编码后的结果，json 格式如下，发送到 mqtt broker 即可： image.json { …

技术｜RV1126 系统安装 Docker 及初始化运行环境
type: item
date: 2023-02-17T03:52:00+00:00
description: 目录 烧录固件 配置 SSH 登录环境 安装 Docker 运行环境 安装 EdgeX 环境 烧录固件 启动为 recovery 模式； 使用 RKDevTool 烧写所需要的固件； 配置 SSH 登录环境 进入 ADB adb shell 修改 sshd_config，增加 root 登录 PermitRootLogin yes 修改 root 密码（可选） passwd 重启 SSHD systemctl restart sshd 登录 SSH 服务器 安装 Docker 运行环境 安装 curl apt install curl 使用脚本安装 Docker curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh 安装完成大概需要 400M 存储空间。 检查 Docker 安装情况 docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 安装 EdgeX 环境 下载 edgex compose git clone https://github.com/edgexfoundry/edgex-compose.git 切换 v2.3.0 版本 git checkout v2.3.0 启动 portainer 容器管理器 修改 portainer 配置文件，127.0.0.1 -> 删除 make portainer 检查 portainer 运行 docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fa14745d381a portainer/portainer-ce "/portainer -H unix:…" 2 minutes ago Up 2 minutes 8000/tcp, 9443/tcp, 0.0.0.0:9000->9000/tcp portainer 登录 web 跑起 EdgeXFoundry 修改镜像，从私有库下载 cd compose-builder make run # 选择需要的容器镜像 查看 Docker 容器运行情况 docker ps 此处，应该显示所有的 已选择 容器。

技术｜RV1126 本地运行 rnkk-toolkit-lite，用 eKuiper 实现 python 视频 AI 推理
type: item
date: 2023-02-13T04:54:00+00:00
description: 接着上一篇文章：技术｜RV1126 本地安装 rnkk-toolkit-lite，实现 python 实施 AI 推理，本文讲述如何在 RV1126 上实现视频流推理； 同时，有两种方法来实现视频分析，1:通过视频采集分析；2:通过定时图片采集分析。这里主要讲述通过 eKuiper 1.8.0 来实现图片定时抓取分析。 前提条件 准备好 RV1126 运行环境 你需要有一个可以运行 rknn 推理框架的硬件设备。 可参照上一篇文章：技术｜RV1126 本地安装 rnkk-toolkit-lite，实现 python 实施 AI 推理 搭建运行环境； 通过开放源码自己编译运行环境：https://github.com/yiqisoft/rv1126-rknn_toolkit_lite-1.7.1； 通过 Docker Hub 仓库运行环境； 如果实在无法运行，可以寻求我司的技术支持：18616669123 基础知识准备 熟悉 RKNN 相关的配置和运行环境，可参考官方文档：https://github.com/rockchip-linux/rknn-toolkit； 高性能 PC，基于 Windows 用于预编译 RKNN 模型，或基于 macOS 用于开发； Docker 开发构建 docker 镜像和运行容器的技能； Linux开发搭建HOST运行环境的技巧； Python脚本调试Python开发技巧； AI/ML 开发深度学习调试技能； GO语言编程技巧； 也就是说，你最好是一位全栈开发者。 配置过程 过程稍有些复杂和繁琐，需要的基础知识很多，请多参考各框架的官方文档。 搭建 eKuiper 运行环境 基础运行环境 官方文档在此：LF Edge eKuiper - 超轻量物联网边缘流处理软件; 主要是 使用 Python 函数插件运行 AI 算法 章节和 视频源 章节; 使用 eKuiper 官方环境，成功运行 pyai 例程在 tflite 环境下跑通推理； 创建视频分析 stream 和 rule 创建视频源 source 创建规则 rule action 可以根据自己的需求，选择合适自己的 Sink 观察结果（mqtt broker） 确保视频源采集成功，且将图片二进制发送出去； 部署 rknn 推理插件 通过开放源码仓库：https://github.com/yiqisoft/rv1126-rknn_toolkit_lite-1.7.1，下载 pyairknn 代码，修改成你需要的功能或不改； 打包压缩成 zip 文件； 上传到 eKuiper Extension 下； 确保 eKuiper 后台程序没有出错，且 RKNN 环境测试后模型正常。 创建 rknn 推理 rule 创建 rule 启动 rule，查看日志，推理成功 验证外部 mqtt broker 接收到推理结果 总结 必须很熟悉 eKuiper 运行环境，熟读官方文档，这个很重要； Docker 环境要玩的好，否则日志都不一定找得到； 插件不能有一点错误，否则看不到任何结果，代码质量要求很高； 基础运行环境的依赖库很头疼，尤其是在 RV1126 的架构是 armv7l 情况下； eKuiper 的 rule 规则用 SQL 来写，还是很有挑战性的工作，各种参数传递，没点能力理解不了； eKuiper 和 eKuiper manager 版本要一致，1.8.0； 算法精度需要自己多琢磨，可能需要训练自己的模型才能达到毕竟好的推理结果； 最后看一下 tflite 在 CPU 上推理 和 rknn 在 NPU 上推理结果对比，快了 100倍；

技术｜RV1126 本地安装 rnkk-toolkit-lite，实现 python 实施 AI 推理
type: item
date: 2023-02-04T07:54:00+00:00
description: RV1126 支持4核CPU（armv7l, 32位架构，很多应用不一定支持），2Tops算力（4路IPC摄像头推理，不在话下），低功耗无风扇，是低端 边缘计算 + AI 应用的低成本选择； rknn-toolkit-lite 支持在 RV1126 上跑 python 应用，方便快速开发和部署； 我司的 边缘计算+AI 网关 YiGATE A600 就是基于此架构设计而成。 1. 准备工作 RV1126 开发板或整机 一台整机是必不可少的要求，可以从网店购买； 安装好支持 docker 环境的 debian 或 ubuntu系统； X86或ARM64 开发机 最好是 X86 的宿主主机开发，否则交叉编译环境不好处理； ARM64 主机开发比较麻烦，要慎重选择； RV1126 SDK 找设备供应商获取 RV1126 的 SDK 开发包； 搭建开发环境请参考开发包说明； 2. docker 环境 ubuntu 安装 docker 环境 参照 docker 官方手册，几条命令安装好； 如果需要的话，安装一个 portainer 容器管理器，方便远程 web 管理 image 镜像和容器； 编辑自己的 Dockerfile，用于编译 RV1126 上的运行微服务环境； RV1126 的 rknn-toolkit-lite 需要的环境很特殊，需要 opencv 3.4.3 运行库（SDK版本限制了）； 自己的 Dockerfile，可以随意选择需要的安装包，自己编译 docker image，占用空间可控； 3. 示例代码 Dockerfile 参考示例 FROM debian:10-slim ARG OPENCV_VERSION ARG DEBIAN_FRONTEND=noninteractive WORKDIR /opt/build RUN set -ex \ && apt-get -qq update \ && apt-get -qq install -y --no-install-recommends \ build-essential cmake \ gcc g++ \ curl wget unzip \ libhdf5-103 libhdf5-dev \ libopenblas-base libopenblas-dev \ libprotobuf17 libprotobuf-dev \ libjpeg62-turbo libjpeg62-turbo-dev \ libpng16-16 libpng-dev \ libtiff5 libtiff-dev \ libwebp6 libwebp-dev \ libopenjp2-7 libopenjp2-7-dev \ libtbb2 libtbb-dev \ libeigen3-dev \ tesseract-ocr tesseract-ocr-por libtesseract-dev \ python3 python3-pip python3-dev \ && wget -q --no-check-certificate https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip -O opencv.zip \ && wget -q --no-check-certificate https://github.com/opencv/opencv_contrib/archive/${OPENCV_VERSION}.zip -O opencv_contrib.zip \ && unzip -qq opencv.zip -d /opt && rm -rf opencv.zip \ && unzip -qq opencv_contrib.zip -d /opt && rm -rf opencv_contrib.zip \ && cmake \ -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D OPENCV_EXTRA_MODULES_PATH=/opt/opencv_contrib-${OPENCV_VERSION}/modules \ -D EIGEN_INCLUDE_PATH=/usr/include/eigen3 \ -D OPENCV_ENABLE_NONFREE=ON \ -D WITH_JPEG=ON \ -D WITH_PNG=ON \ -D WITH_TIFF=ON \ -D WITH_WEBP=ON \ -D WITH_JASPER=ON \ -D WITH_EIGEN=ON \ -D WITH_TBB=ON \ -…

白皮书｜YiEDGE-亿琪边缘计算软件
type: item
date: 2022-12-15T00:12:00+00:00

YiAI 人工智能算法-动物姿态识别
type: item
date: 2022-07-27T10:18:13+00:00

YiAI 人工智能算法路况测试视频
type: item
date: 2022-07-22T09:37:46+00:00

Cosine similarity 余弦相似性原理及其应用
type: item
date: 2020-06-04T13:57:00+00:00
description: 什么是余弦相似性 余弦相似性通过测量两个向量的夹角的余弦值来度量它们之间的相似性。0度角的余弦值是1，而其他任何角度的余弦值都不大于1；并且其最小值是-1。从而两个向量之间的角度的余弦值确定两个向量是否大致指向相同的方向。两个向量有相同的指向时，余弦相似度的值为1；两个向量夹角为90°时，余弦相似度的值为0；两个向量指向完全相反的方向时，余弦相似度的值为-1。这结果是与向量的长度无关的，仅仅与向量的指向方向相关。余弦相似度通常用于正空间，因此给出的值为0到1之间。 注意这上下界对任何维度的向量空间中都适用，而且余弦相似性最常用于高维正空间。例如在信息检索中，每个词项被赋予不同的维度，而一个文档由一个向量表示，其各个维度上的值对应于该词项在文档中出现的频率。余弦相似度因此可以给出两篇文档在其主题方面的相似度。 另外，它通常用于文本挖掘中的文件比较。此外，在数据挖掘领域中，会用到它来度量集群内部的凝聚力。 定义 两个向量间的余弦值可以通过使用欧几里得点积公式推导： 给定两个属性向量， A 和B，其余弦相似性θ由点积和向量长度给出，如下所示： 这里的A_i和B_i分别代表向量A和B的各分量。 给出的相似性范围从-1到1：-1意味着两个向量指向的方向正好截然相反，1表示它们的指向是完全相同的，0通常表示它们之间是独立的，而在这之间的值则表示中间的相似性或相异性。 对于文本匹配，属性向量A 和B 通常是文档中的词频向量。余弦相似性，可以被看作是在比较过程中把文件长度正规化的方法。 在信息检索的情况下，由于一个词的频率（TF-IDF权）不能为负数，所以这两个文档的余弦相似性范围从0到1。并且，两个词的频率向量之间的角度不能大于90°。 角相似性 “余弦相似性”一词有时也被用来表示另一个系数，尽管最常见的是像上述定义那样的。透过使用相同计算方式得到的相似性，向量之间的规范化角度可以作为一个范围在[0,1]上的有界相似性函数，从上述定义的相似性计算如下： 在这一公式中，向量系数可能是正，也可能是负。 或者，用以下式子计算 而在这一式子中，向量系数总是正的。 虽然“余弦相似性”一词有时会用来表示这个角距离，但实际上很少这样说，因为角度的余弦值只是作为一种计算角度的简便方法而被用到，本身并不是意思的一部分。角相似系数的优点是，当作为一个差异系数（从1减去它）时，在不为第一种意义的情况下，产生的函数是一个严格距离度量。然而，对于大多数的用途，这不是一个重要的性质。若对于某些情况下，只有一组向量之间的相似性或距离的相对顺序是重要的，那么不管是使用哪个函数，所得出的顺序都是一样的。 与“Tanimoto”系数的混淆 有时，余弦相似性会跟一种特殊形式的、有着类似代数形式的相似系数相混淆： 事实上，这个代数形式是首先被Tanimoto定义，作为在所比较集合由位元向量表示时计算其Jaccard系数的方法。虽然这公式也可以扩展到向量，它具有和余弦相似性颇为不同的性质，并且除了形式相似外便没有什么关系。 Ochiai系数 这个系数在生物学中也叫Ochiai系数，或Ochiai-Barkman系数： 这里A和B是集合，n(A)是A的元素个数。如果集合由位元向量所代表，那么可看到落和系数跟余弦相似性是等同的。 应用 我们还希望找到与原文章相似的其他文章。比如，"Google新闻"在主新闻下方，还提供多条相似的新闻。为了找出相似的文章，需要用到"余弦相似性"（cosine similiarity）。下面，我举一个例子来说明，什么是"余弦相似性"。 简单起见，我们来看看下面的句子： A：我喜欢看电视，不喜欢看电影。 B：我不喜欢看电视，也不喜欢看电影。 请问怎样才能计算上面两句话的相似程度？ 基本思路是：如果这两句话的用词越相似，它们的内容就应该越相似。因此，可以从词频入手，计算它们的相似程度。 第一步：分词 A：我/喜欢/看/电视，不/喜欢/看/电影。 B：我/不/喜欢/看/电视，也/不/喜欢/看/电影。 第二步：列出所有的词、字 我，喜欢，看，电视，电影，不，也 第三步：计算词频 A：我 1，喜欢 2，看 2，电视 1，电影 1，不 1，也 0。 B：我 1，喜欢 2，看 2，电视 1，电影 1，不 2，也 1。 第四步：描述词频向量 A：[1, 2, 2, 1, 1, 1, 0] B：[1, 2, 2, 1, 1, 2, 1] 到这里，问题就变成了如何计算这两个向量的相似程度。 我们可以把它们想象成空间中的两条线段，都是从原点（[0, 0, ...]）出发，指向不同的方向。两条线段之间形成一个夹角，如果夹角为0度，意味着方向相同、线段重合；如果夹角为90度，意味着形成直角，方向完全不相似；如果夹角为180度，意味着方向正好相反。因此，我们可以通过夹角的大小，来判断…