边缘计算+WEB端应用融合:AI行为识别智能监控系统搭建指南 -- 边缘设备图像识别及部署(二)

news2024/9/21 20:53:37

专栏目录
边缘计算+WEB端应用融合:AI行为识别智能监控系统搭建指南 – 整体介绍(一)

边缘计算+WEB端应用融合:AI行为识别智能监控系统搭建指南 -- 边缘图像识别及部署(二)

  • 前言
  • 边缘图像识别与推流
    • 整体思路
    • 原始视频信号
    • 部分核心代码
    • 配置文件清单
  • 程序包部署
    • 模式1:TF卡烧录部署
    • 模式2:程序包部署
      • 打包

前言

欢迎来到我们的专栏《边缘计算+WEB端应用融合:AI行为识别智能监控系统搭建指南》!在这个专栏中,我们将带您深入探索如何将边缘计算和WEB端应用相结合,打造智能监控系统,实现对各种行为的实时识别和监测。无论您是想在家庭、办公场所还是公共区域建立智能监控系统,本专栏都将为您提供全面的指导和实用的技巧。让我们一起探索边缘计算技术的无限可能,构建出更加智能、高效的监控系统吧!

本专栏系统完整搭建将用到C++(边缘设备程序)、Python(模型训练、网络通信)、JAVA(系统后端)、VUE3(系统前端)、SQL(数据库)等开发语言。在搭建之前我自己也只会JAVA和SQL,所以完全不用担心语言不会导致无法搭建。所有的算力都由边缘设备提供,所以不需要高性能服务器,成本上也可以得到控制。

项目特点:低成本搭建视频智能识别、边缘计算终端和网页端完全打通自由控制、除常规标注检测外增加了预警和区域检测功能。

申明:本系统完全由博主自己一人搭建,其中使用到的都是开源项目,如:若依、RKNN、zlmediakit等。
PS:国人的开源项目越来越牛了。
在这里插入图片描述

边缘图像识别与推流

整体思路

在上一篇文章中有介绍道,我这个项目所采用的边缘计算设备是基于国产芯片RK3588。目前开发出来的是一代产品的程序包,命名为YunYan_V1.0(云眼1.0)。
YunYan_V1.0采用C++编写,核心采用的是yolov5的图像识别能力,支持多线程的图像识别,充分调用RK3588的三个NPU进行图像识别。并且利用zlmediakit将对视频图像的读推流进行了高度集成。以下是代码的大致思路:

Created with Raphaël 2.3.0 开始 读取配置文件 初始化模型、视频解码器、视频编码器、线程池 解码帧画面推送至识别线程池 从识别线程池中获取识别结果 绘制检测框、识别预警并保留视频、帧画面推流 运行不正常? 结束 yes no

原始视频信号

其中有一个问题就是怎么获取原始的视频流信息?我个人在开发中主要是获取三种流方式:
方式1:模拟视频流
模拟是通过mediamtx和ffmpeg实现的,通过一台局域网内的设备进行模拟信号的输送就可以实现获取rtsp流的目的,我自己用的就是闲置的树莓派
mediamtx下载地址:https://github.com/bluenviron/mediamtx/releases
ffmpeg官网:https://ffmpeg.org/ffmpeg.html,ffmpeg网上有很多安装教程可以根据自身系统版本搜索。

nohup ./mediamtx mediamtx.yml > mediamtx.log 2>&1 &
nohup ffmpeg -re -stream_loop -1 -i /home/medias/test.mp4 -vcodec copy -acodec copy -b:v 5M -f rtsp -rtsp_transport tcp rtsp://localhost:8554/live.sdp > testffmpeg.log 2>&1 &
rtsp://192.168.124.31:8554/live.sdp

方式2:网络摄像头原始视频流【海康设备】

rtsp://admin:XXXXXX@192.168.124.38:554/h265/ch1/main/av_stream

方式3:网络录像机原始视频流【海康设备】

rtsp://admin:XXXXXXX@192.168.124.29:554/Streaming/Channels/101

部分核心代码

以下是部分 核心代码片

  1. 创建线程池
// 创建线程池
yolo_thread_pool = new Yolov5ThreadPool(); 
// 初始化线程池
// 参数1:模型文件地址
// 参数2:线程数量
// 参数3:非极大值抑制
// 参数4:置信度
// 参数5:模型标签文件路径
// 参数6:标签数量                                                                          
yolo_thread_pool->setUp(model_path, num_threads, NMS_threshold, box_threshold, model_label_file_path, obj_class_num); 
  1. 定义解码器
MppDecoder *decoder = new MppDecoder();  // 创建解码器
decoder->Init(video_type, app_ctx.source_frame_rate, &app_ctx); // 初始化解码器
// mpp在每次解析后都会回调mpp_decoder_frame_callback方法
decoder->SetCallback(mpp_decoder_frame_callback); // 设置回调函数,用来处理解码后的数据
app_ctx.decoder = decoder;
  1. 解码后处理
// 这里利用了rk3588自带的rga进行颜色通道的转换:YUV420SP -> RGB888
// 也可以使用opencv
origin = wrapbuffer_fd(fd, width, height, RK_FORMAT_YCbCr_420_SP, width_stride, height_stride);
src = wrapbuffer_fd(mpp_frame_fd, width, height, RK_FORMAT_YCbCr_420_SP, width_stride, height_stride);
cv::Mat origin_mat = cv::Mat::zeros(height, width, CV_8UC3);
rga_buffer_t rgb_img = wrapbuffer_virtualaddr((void *)origin_mat.data, width, height, RK_FORMAT_RGB_888);
imcopy(origin, rgb_img);
// 提交推理任务给线程池
yolo_thread_pool->submitTask(origin_mat, job_cnt++);
  1. 获取处理结果并绘制预警
std::vector<Detection> objects;
// 获取推理结果
auto ret_code = yolov5_thread_pool->getTargetResultNonBlock(objects, result_cnt);
// 遍历检测结果并且进行判断
for (const auto &object : objects)
{
    auto iter = ctx->labels_map.find(object.className);
    // 设置参数判断是否全图警戒,1为全图
    bool temp_ret = true;
    if (ctx->enable_region == 1 && ctx->g_ploygon.size() > 0)
    {
        Point p = {
            object.box.x + object.box.width / 2,
            object.box.y + object.box.height / 2};
        // 判断是否在预警区域中
        temp_ret = isInside(ctx->g_ploygon, p);
    }
    double value = iter->second;
    // 判断识别对象是否在识别要素中,同时判断要素是否在警戒区域中,执行度大于设定值
    if (iter != ctx->labels_map.end() && temp_ret && object.confidence >= value)
    {
        cv::rectangle(img, object.box, cv::Scalar(255, 0, 0), 2);
        // class name with confidence
        std::string draw_string = object.className + " " + std::to_string(object.confidence);
        cv::putText(img, draw_string, cv::Point(object.box.x, object.box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 1,
                    cv::Scalar(255, 0, 0), 2);
        // 在迭代中发现了存在异常的标记,进行临时变量标记,此变量可能会在过程中重复赋值。
        if_warning_hold = true;
    }
    else
    {
        cv::rectangle(img, object.box, object.color, 2);
        // class name with confidence
        std::string draw_string = object.className + " " + std::to_string(object.confidence);
        cv::putText(img, draw_string, cv::Point(object.box.x, object.box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 1,
                    cv::Scalar(255, 0, 255), 2);
    }
}
  1. 检测结果推流
 // mk的参数初始化
char *ini_path = mk_util_get_exe_dir(ctx->mk_file_path.c_str());
mk_config config = {
        .thread_num = 10,
        .log_level = 0,
        .log_mask = LOG_CONSOLE,
        .log_file_path = NULL,
        .log_file_days = 0,
        .ini_is_path = 1,
        .ini = ini_path,
        .ssl_is_path = 1,
        .ssl = NULL,
        .ssl_pwd = NULL
};

// memset(&config, 0, sizeof(mk_config));
// config.log_mask = LOG_CONSOLE;
// 初始化环境,调用该库前需要先调用此函数
mk_env_init(&config);
mk_free(ini_path);
// 在端口80上启动HTTP服务器
if (ctx->enable_http == 1)
    mk_http_server_start(ctx->push_http_port, 0);
// 在端口554上启动RTSP服务器
if (ctx->enable_rtsp == 1)
    mk_rtsp_server_start(ctx->push_rtsp_port, 0);
// 在端口1935上启动RTMP服务器
if (ctx->enable_rtmp == 1)
    mk_rtmp_server_start(ctx->push_rtmp_port, 0);
if (ctx->enable_rtc == 1)
    mk_rtc_server_start(ctx->push_rtc_port);
// 创建一个新的Codeium播放器
ctx->player = mk_player_create();
ctx->stream_url = url;
// 设置处理播放事件的回调函数
mk_player_set_on_result(ctx->player, on_mk_play_event_func, ctx);
// 设置播放被异常中断的回调
mk_player_set_on_shutdown(ctx->player, on_mk_shutdown_func, ctx);
// 播放来自提供的RTSP URL的视频流
mk_player_play(ctx->player, ctx->stream_url);
// 推流
ret = mk_media_input_h264(ctx->media, enc_data, enc_data_size, millis, millis);

根据以上代码无法完整完成编码工作,由于本专栏主要方向是关于边缘计算设备和WEB端应用的融合,实现AI行为识别的智能监控系统。所以不会对终端设备的实际使用技术及代码原理进行特别详细的描述。如果读者有需要可以留言,我可以出一个关于RK3588的独立专栏。
其实本质上边缘计算设备无论是选择RK3588,还是带有GPU的主机都可以,本项目是为了减少项目的搭建预算所以找的更便宜的解决方案,同时也能符合国产化、信创需要。

配置文件清单

以下是YunYan_V1.0提供的参数清单:

[YUNYAN]
# 进程的唯一编号,这是一个uid
CEProcessId = b6cf4e7e-b952-4bf5-be29-0225f71d7f57
# 模型路径,必须是完整路径yolo5s_cx_200
ModelPath = /home/YunYan-V1/weights/yolov5s.rknn
# IOU
NMSThreshold = 0.65
# 置信度
BoxThreshold = 0.4
# 模型的labels文件路径
ModelLabelsFilePath = /home/YunYan-V1/coco_80_labels_list.txt
# 推理类型数量 yolov5 80
ObjClassNum = 80
# 流地址
StreamUrl = rtsp://192.168.124.31:8554/live3.sdp
# 视频流类型264/265,default 264,265格式目前不支持
VideoType = 264
# 原始视频帧率
SourceFrameRate = 25
# 启动监测的线程数,default 12
NumThreads = 20
# 是否开启hls播放功能,default 0,需要和EnableHttp同时开启
EnableHls = 0
# 是否开启hls播放功能,default 0
EnableHttp = 0
# http推流端口,default 80
PushHttpPort = 80
# 是否开启rtsp推流
EnableRtsp = 1
# rstp推流端口,default 554
PushRtspPort = 554
# 是否开启rtsp推流
EnableRtmp = 0
# rtmp推流端口,default 1935
PushRtmpPort = 1935
# 是否开启rtc
EnableRtc = 0
# rtc推流端口,default 8000
PushRtcPort = 8001
# 推流地址设定1
PushPathFirst = yunyan-live
# 推流地址设定2
PushPathSecond = test
# 工作时间设置{8,30,13,30}${14,0,17,30}
WorkTimeRanges = {11,00,17,10}
# 识别的labels,用英文$分割
# {clock,0.8}${chair,0.8}
LabelsAndConfidence = {person,0.5}
#一场追踪到多少秒才触发预警视频的录制
WarningHoldUpTime = 3
# 预警间隔时间秒,如果设置数值过小会导致视频文件未完成存储就连续存储问题
WarningIntervalTime = 60
# 预警视频长度秒
WarningShowTime = 5
# 预警视频帧率,这个帧率设置的是视频输出,但是实际帧率会和原始帧率有关。
# 如果原始帧率25,预警帧率是5,将会每5帧记录一次可以帧除。
# 如果原始帧率25,预警帧率10,将会每2帧记录一次,视频感觉感觉会变慢。
WarningShowFrameRate = 10
# 预警视频保存路径
WarningFilePath = /home/yunyan_warning/
# 预警视频的信息字段
WarningFileInfo = _bad_
# 是否启动区域检测,default 0
EnableRegion = 1
# 区域检测点位文件地址 
RegionFilePath = /home/YunYan-V1/region.txt
# MK配置文件地址
MkFilePath = mk_config.ini

程序包部署

由于边缘计算设备都是采用相同的系统版本,所以整体上有2种部署模式。

模式1:TF卡烧录部署

如果玩过小机器的基本对这种都不陌生,但是在这个项目中并不推荐。TF烧录是对系统内容原模原样的复制,可能会导致设备的IP冲突。路由器在给设备分配IP的时候是通过系统的特征mac进行分配的,但是烧录的系统mac地址都是相同的。如果局域网内只有一台设备不会有问题,如果存在多台设备需要通过一些补丁方式来修复,反正我不是很喜欢。
如果用这种方式可以参考:https://blog.csdn.net/Altitude_/article/details/131593735

模式2:程序包部署

打包

YunYan_V1.0的打包编译管理使用的是cmake,通过cmake打包成yunyan-1.0.0-Linux.deb。边缘计算设备只需要安装上默认的ubuntu系统后使用dpkg -i yunyan-1.0.0-Linux.deb 就可以安装。
如果是第一次安装需要根据readme中的要求对两个py脚本进行定时器配置,之后就可以全自动运行了。

##需要python安装requests
sudo apt-get python3-pip
pip install requests
#设定激活函数定时任务
#默认yunyan-cv.py每5分钟执行一次并记录执行日志
crontab -e
*/5 * * * * /usr/bin/python3 /usr/local/yunyancv/yunyan-cv.py >> /usr/local/yunyancv/yunyan-cv-py.log 2>&1
#设定预警函数定时任务
#默认yunyan-warning.py每5分钟执行一次并记录执行日志
crontab -e
*/5 * * * * /usr/bin/python3 /usr/local/yunyancv/yunyan-warning.py >> /usr/local/yunyancv/yunyan-warning-py.log 2>&1

yunyan-cv.py主要负责和云端系统进行通讯,告知平台设备的存活状态,并且会从云端系统获取最新的配置信息,如果需要配置会主动驱动进程进行在线更新。同时这也是一个进程保护程序,如果发现进程死亡会自动重启进程。
yunyan-warning.py主要是负责将预警视频和预警信息推送给云端,并保证本地存储的健康,定期删除无用文件。

如果你喜欢这篇博客请点赞留言,后续会更新在部署完成后怎么打破网络限制在公网进行通信。

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

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

相关文章

蓝桥杯刷题总结(Python组)

1、蛇形矩阵 解题思路&#xff1a;每次赋值后都对方向进行改变&#xff0c;一般上下左右就是&#xff08;-1&#xff0c;0&#xff09;&#xff0c;&#xff08;0&#xff0c;1&#xff09;&#xff0c;&#xff08;1&#xff0c;0&#xff09;&#xff0c;&#xff08;0&…

分布式事务的解决方案--Seata架构

一、Seata的XA模式 二、AT模式原理 三、TCC模式原理 四、MQ分布式事务 异步&#xff0c;非实时&#xff0c;实现最终的一致性。 四、分布式事务的解决方案

【MLLM+轻量多模态模型】24.02.Bunny-v1.0-2B-zh: 轻量级多模态语言模型 (效果一般)

24.02 北京人工智能研究院&#xff08;BAAI&#xff09;提出以数据为中心的轻量级多模态模型 arxiv论文&#xff1a;2402.Efficient Multimodal Learning from Data-centric Perspective 代码&#xff1a;https://github.com/BAAI-DCAI/Bunny 在线运行&#xff1a;https://wis…

CSS元素定位(学习笔记)

一、 z-index 1.1 作用 规定元素的堆叠顺序,取值越大&#xff0c;层级越往上 1.2 属性值 属性值为数字&#xff0c;可以取负值&#xff0c;不推荐 默认值&#xff1a;auto(跟父元素同一层级) 1.3 注意 必须配合定位(static除外)使用&#xff0c;默认情况下&#xff0c;后面的元…

openssl3.2 - exp - openssl speed test

文章目录 openssl3.2 - exp - openssl speed test概述笔记表面上能列出的算法集合没列出的算法, 有的也支持不支持的算法的例子直接提示算法不支持算法的属性找不到到底哪些算法才是可以测试的算法?那看看哪些算法是支持的?包含支持的算法的名称数组在算法失败的提示处, 将支…

【Redis】缓存穿透

问题发生背景&#xff1a;客户端请求的数据再缓存中和数据库中都不存在。 导致的问题&#xff1a;缓存永远不会生效&#xff0c;这些请求都会去请求数据库—导致数据库压力增大。 解决方案&#xff1a; 1.缓存空对象 在Redis中缓存空对象&#xff0c;告诉客户端数据库中没有该值…

Python快速导入id至json文件(2024.3.19)

Python实现id导入至json文件 2024.3.19 需求分析1、输入数据介绍1.1 三个.txt文件1.1.1 computers.txt&#xff08;计算机&#xff09;1.1.2 cameras.txt&#xff08;摄像头&#xff09;1.1.3 monitors.txt&#xff08;显示器&#xff09; 1.2 单个.xlsx文件 2、实现思路3、Pyt…

Day21:实现退出功能、开发账号设置、检查登录状态

实现退出功能 将登录凭证修改为失效状态。跳转至网站首页。 数据访问层 不用写了&#xff0c;已经有了updateStatus方法&#xff1b; 业务层 UserService public void logout(String ticket) {loginTicketMapper.updateStatus(ticket, 1);}Controller层 RequestMapping(p…

opc客户端

支持opc&#xff0c;da&#xff0c;ua通信&#xff08;匿名登陆及用户登陆&#xff09; 支持批量节点数据监听&#xff0c;当数据有变化时更新 支持单个节点读取和写入 KeepServer做为modbus server keepserver通信配置 https://blog.csdn.net/xiaochenXIHUA/article/detail…

【Qt问题】使用QSlider创建滑块小部件无法显示

问题描述&#xff1a; 使用QSlider创建滑块小部件用于音量按钮的时候&#xff0c;无法显示&#xff0c;很奇怪&#xff0c;怎么都不显示 一直是这个效果&#xff0c;运行都没问题&#xff0c;但是就是不出现。 一直解决不了&#xff0c;最后我在无意中&#xff0c;在主程序中…

【开发】Redis 的理解与数据存储格式

目录 相关传送门 1. NOSQL和关系型数据库比较 2. 主流的NOSQL产品 3. Redis的理解 4. redis数据存储格式 4.1 String 4.2 Hash 4.3 List 4.4 Set 4.5. sorted_set 注&#xff1a;手机端浏览本文章可能会出现 “目录”无法有效展示的情况&#xff0c;请谅解&#xf…

2、RabbitMQ_安装

RabbitMQ安装文档 RabbitMQ官网下载地址&#xff1a;https://www.rabbitmq.com/download.html 1.安装依赖 在线安装依赖环境&#xff1a; yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel tk tc x…

【算法与数据结构】二叉树(前中后)序遍历

文章目录 &#x1f4dd;前言&#x1f320; 创建简单二叉树&#x1f309;二叉树的三种遍历&#x1f320;前序&#x1f309;中序遍历 &#x1f320;后序遍历 &#x1f320;二叉树节点个数&#x1f309;二叉树节点个数注意点 &#x1f6a9;总结 &#x1f4dd;前言 一棵二叉树是结…

为什么选择 Flink 做实时处理

优质博文&#xff1a;IT-BLOG-CN 为什么选择 Flink 【1】流数据更真实地反映了我们的生活方式&#xff08;实时聊天&#xff09;&#xff1b; 【2】传统的数据架构是基于有限数据集的&#xff08;Spark 是基于微批次数据处理&#xff09;&#xff1b; 【3】我们的目标&#xf…

C语言-memset(改变数值函数)

memset&#xff08;改变数值函数&#xff09; 函数的语法 &#xff08;第几个元素&#xff0c;改变成什么元素&#xff0c;几个字节&#xff09; memset函数是C语言标准库函数之一&#xff0c;用于将内存中的某一块区域全部设置为某个特定的值。它定义在<string.h>头文…

MyBatisPlus 之四:MP 的乐观锁和逻辑删除、分组、排序、链式的实现步骤

乐观锁 乐观锁是相对悲观锁而言的&#xff0c;乐观锁假设数据一般情况不会造成冲突&#xff0c;所以在数据进行提交更新的时候&#xff0c;才会正式对数据的冲突与否进行检测&#xff0c;如果冲突&#xff0c;则返回给用户异常信息&#xff0c;让用户决定如何去做。 乐观锁适用…

服务器数据恢复—光纤环境互斥不当导致存储VMFS卷损坏的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 某公司的信息管理平台&#xff0c;通过3台虚拟机共享了一台存储设备供企业内部使用&#xff0c;存储设备中存放了公司内部重要的数据文件。 由于业务增长的需要&#xff0c;管理员又在这个存储网络上连接了一台Windows server服务器&a…

供应链投毒预警 | 开源供应链投毒202402月报发布啦

概述 悬镜供应链安全情报中心通过持续监测全网主流开源软件仓库&#xff0c;结合程序动静态分析方式对潜在风险的开源组件包进行动态跟踪和捕获&#xff0c;发现大量的开源组件恶意包投毒攻击事件。在2024年2月份&#xff0c;悬镜供应链安全情报中心在NPM官方仓库&#xff08;…

uniapp可视范围高度 - 用户屏幕可操作的屏幕高度 - 适用于APP、H5@公众号、纯H5@Chrome

可视范围高度 let heightPx uni.getWindowInfo().windowHeight uni.getWindowInfo().windowTop 官方手册 uni.getWindowInfo() | uni-app官网uni-app,uniCloud,serverless,uni.getWindowInfo()https://uniapp.dcloud.net.cn/api/system/getWindowInfo.html 实测数据 uni.ge…

【C++初阶】第七站:string类的初识(万字详解、细节拉满)

前言&#xff1a; &#x1f4cd;本文知识点&#xff1a;string的初识 本专栏&#xff1a;C 目录 一、什么是STL 二、STL的六大组件 三、STL的缺陷 四、为什么学习string类&#xff1f; 五、标准库中的string类 1、string类(了解) 2、string类的常用接口说明&#xff08;…