yolo11目标检测结果Web可视化-----基于华为的presenter库 (3)目标检测结果上传Web界面(c++版本)
文章目录
1 概要
最近在学习如何将目标检测的结果推送到网页上进行可视化,经过一系列的搜寻,查找,最终准备基于华为的presenter库进行Web页面可视化。
华为的presenter库分为两个,一个是presenterserver,一个是presenteragent,前者是用来搭建局域网网站同时开启监听端口,后者是在运行目标检测模型时,打包检测数据用来传输到presenterserver的库,presenterserver库介绍链接如下:(可以不用去管,博主会提供相应改好的文件)
presenterserver库 python版本
presenterserver库 c++版本
presenterserver和presenteragent库简略介绍
最终基于presenter库,我们通过以下两步即可实现检测结果于Web界面的可视化:
- 用于展示Web界面的设备(可以是你跑目标检测程序的主机,或者是另外一个在同一局域网内的设备)运行presenteragent库中的Presenter Server源码,该源码在局域网内创建通过指定接口(如10.0.0.2:7007)创建Web页面,同时通过另一指定接口(如10.0.0.2:7006)进行消息的监听,监听得到的消息会传给Web界面。
- 运行目标检测程序的设备使用presenteragent库中的Presenter agent源码,将消息传输至监听的接口,如1中指定的10.0.0.2:7006,传输成功后结果即可可视化。
注意,如果你用的是同两个个设备,一个进行目标检测,一个进行Web界面可视化,则两者之间需要保持在同一局域网。如果你用的是同一个设备既进行目标检测,也进行Web界面可视化,则无需在意ip设置。
本章节在python环境下进行数据的上传,在Web端进行可视化展示,将会使用到华为的官方的presenteragent库,其链接如下:
需要设备:PC宿主机(Linux系统)。
整体流程如下:
1.下载python版本的presenteragent库并安装好依赖环境。
2.使用presenteragent库提供的接口函数,打包数据并上传Web端进行可视化展示。
2 presenteragent库
2.1 介绍
Presenter Agent提供一系列API,用户可以调用这些API向Presenter Server推送媒体消息,并在浏览器中查看。当前支持JPEG格式图片的推送。
调用流程如下所示:
- App调用OpenChannel函数打开与Presenter Server间的通道。
- App调用SendMessage函数在该通道上推送媒体消息。推送消息时, 支持在推送的图片上画矩形框。使用时需要将框的左上、右下点的坐标、框的标题设置到PresentImageRequest对象中。
- 所有图片发送完成后,App调用CloseChannel函数释放分配的资源。
对应第一章节的图的前半部分流程,即:
2.2 下载presenteragent库
下载方式有2个
2.2.1 直接从华为官网下载
git clone https://gitee.com/ascend/samples.git
进入如下目录:
presenteragent即是我们需要的agent文件夹(使用时候可以把整个common文件夹复制下来),之后可以放置在你的工程文件夹中:
2.2.2 从我提供的百度网盘链接中下载(推荐)
博主在这个文件中抽离了和华为硬件相关的配置,直接用华为官网的可能需要改一下LOGGER函数,不然会报错)
presenteragent百度网盘链接:里面有C++对应的版本
通过网盘分享的文件:c_present_v2
链接: https://pan.baidu.com/s/1RFJo7sxk-jFkvJh9W2Lxjg 提取码: 1234
3 presentagent库
首先presentagent库会基于protobuf包使用,因此我们得先下载protobuf包并交叉编译获得我们需要得对应架构版本,如arm32,arm64,x86等架构。博主使用的是硬件是imx6ull与rk3568,为arm32架构。
3.1 安装protobuf包
# 安装protobuf相关依赖
sudo apt-get install autoconf automake libtool
# 下载protobuf源码
cd ${HOME}
git clone -b 3.13.x https://gitee.com/mirrors/protobufsource.git protobuf
# 编译安装protobuf
cd protobuf
./autogen.sh
# 修改配置文件,指定你安装的架构版本与交叉编译工具链
#--prefix=/home/book//Desktop/Web_visualize/arm 为你的库安装的路径
# CC CXX为你交叉编译工具所在的目录
./configure --host=arm-linux --prefix=/home/book//Desktop/Web_visualize/arm CC=/home/book/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-gcc CXX=/home/book/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-g++
make clean
make -j8
sudo make install
执行完成后在我们指定的安装目录下有如下文件:lib中的即为我们的库文件,和lib一个文件下的还有bin文件夹,那个是用来测试的,可以不管
具体其他架构版本的安装请参考:
protobuf、protobuf-c、protobuf-c-rpc在Linux(Ubuntu18.04)编译安装及交叉编译arm\aarch64版本
3.2 安装presentagent库
进入你下载的presentagent文件夹,查看Makefile文件
使用命令
export ARCH=arm #此处改为你设备的架构
export THIRDPART_PATH=/home/book/Desktop/Web_visualize/arm #之前你安装protobuf的路径位置
# 导入你的交叉编译工具链路径位置
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/book/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
vi Makefile
之后设置一下你的交叉编译工具名称即可
之后wq!退出,执行如下命令
#编译你的protobuf结构,之后传输要符合此结构
cd ./proto
${THIRDPART_PATH}/bin/protoc presenter_message.proto --cpp_out=./
cd ..
# 有时候可能得先删除out目录
make -j4
make install
在之前安装protobuf路径下出现libpresenteragent.so即安装成功
4 运行presenteragent库传输检测结果(c++)
4.1将可执行文件上传到运行目标检测代码的设备
因为博主是在ubuntu18.04虚拟机中交叉编译的arm32架构版本,之后将会使用imx6ull运行目标检测代码,因此我需要将可执行文件上传到imx6ull开发板上。
在终端执行如下命令:
#连接开发板
adb shell
#将/home/book/Desktop/Web_visualize/arm/lib/文件夹下的可执行文件全传入到开发板的/lib目录下
adb push /home/book/Desktop/Web_visualize/arm/lib/* /lib
接下来把presenteragent库函数融入你的工程中,如下

接下来还需要两步骤:
1.修改网络配置文件
2.把结果是上传函数融入你的工程中
1.修改网络配置文件
打开param.conf,保持ip配置和1中的一致即可
2.把结果是上传函数融入你的工程中
添加如下定义函数(博主这里是直接加入到main函数的文件中了,没有单独写.h, .c):
//---------------------------------------link to web
#define SUCCESS 1
#define FAILED 0
Channel* g_channel = nullptr;
bool link_to_web(Channel*& _g_channel_)
{
_g_channel_ = nullptr;
PresenterErrorCode openChannelret = OpenChannelByConfig(_g_channel_, "./param.conf");
if (openChannelret != PresenterErrorCode::kNone) {
std::cout << "Open channel failed, error " << (int)openChannelret << "\n" << std::endl;
return false;
}
return true;
}
void EncodeImage(vector<uint8_t>& encodeImg,const cv::Mat& origImg)
{
vector<int> param = vector<int>(2);
param[0] = CV_IMWRITE_JPEG_QUALITY;
param[1] = 95; // default(95) 0-100
// Jpeg images must serialize the Proto message before they can be sent
cv::imencode(".jpg", origImg, encodeImg, param);
}
bool SendImage(vector<DetectionResult>& detectionResults,const cv::Mat& origImg)
{
vector<uint8_t> encodeImg;
EncodeImage(encodeImg, origImg);
ImageFrame imageParam;
imageParam.format = ImageFormat::kJpeg;
imageParam.width = origImg.cols;
imageParam.height = origImg.rows;
printf("w,h = %d %d\n",imageParam.width,imageParam.height);
imageParam.size = encodeImg.size();
imageParam.data = reinterpret_cast<uint8_t*>(encodeImg.data());
imageParam.detection_results = detectionResults;
if(g_channel == nullptr){
printf("channel is nullptr, try to connect once");
link_to_web(g_channel);
}
PresenterErrorCode errorCode = PresentImage(g_channel, imageParam);
if (errorCode != PresenterErrorCode::kNone) {
cout << "PresentImage failed " << static_cast<int>(errorCode) << endl;
return FAILED;
}
return SUCCESS;
}
获得检测结果并上传(红框中的部分即为所有传输需要的过程代码):
vector<DetectionResult> detectResults;
objects.resize(count);
for (int i = 0; i < count; i++)
{
DetectionResult oneResult;
objects[i] = proposals[picked[i]];
// adjust offset to original unpadded
float x0 = (objects[i].rect.x - (wpad / 2)) / scale;
float y0 = (objects[i].rect.y - (hpad / 2)) / scale;
float x1 = (objects[i].rect.x + objects[i].rect.width - (wpad / 2)) / scale;
float y1 = (objects[i].rect.y + objects[i].rect.height - (hpad / 2)) / scale;
// clip
x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f);
y0 = std::max(std::min(y0, (float)(img_h - 1)), 0.f);
x1 = std::max(std::min(x1, (float)(img_w - 1)), 0.f);
y1 = std::max(std::min(y1, (float)(img_h - 1)), 0.f);
objects[i].rect.x = x0;
objects[i].rect.y = y0;
objects[i].rect.width = x1 - x0;
objects[i].rect.height = y1 - y0;
oneResult.lt.x = x0;
oneResult.lt.y = y0;
oneResult.rb.x = x1;
oneResult.rb.y = y1;
oneResult.result_text = class_names[objects[i].label] + std::to_string(objects[i].prob*100) + "\%";
detectResults.emplace_back(oneResult);
}
SendImage(detectResults, bgr);
最后即可实现结果的上传,最终展示视频如下,因为使用的是imx6ull,所以检测速度会慢一些。
5 演示结果
结果演示视频
6 总结
本章节讲述了在使用c++的情况下如何使用华为的presenteragent库,博主个人建议新手使用python版本,更方便一些。
7 章节链接
yolo11目标检测结果Web可视化-----基于华为的presenter库 (1)目标检测结果展示界面的开启
yolo11目标检测结果Web可视化-----基于华为的presenter库 (2)目标检测结果上传Web界面(python版本)
更多推荐



所有评论(0)