本篇继续描述如何在3399上结合前面网络摄像头进行AI识别的情况,目前我们使用最新的yolov5模型进行识别。关于该模型使用的rknn_api,可上3399相关论坛官网下载,1808驱动需更新至1.6以上。
官网给的实例,都是分析一张图片,讲识别结果再次绘制到图片上。python的接口可能更多,丰富点,支持直接拉流分析。但是怎么通过c++接口拉流进行分析呢,进一步,我们是否可以分析多路码流。在不要求识别帧率的情况下,我们识别多路视频这是可行的。
首先我们确定AI识别的流程
加载模型数据-初始化计算棒-通过api接口传入图片RGB数据-分析得出结果-画框标识
通过流程我们可以看出,加载模型初始化计算棒是固定的,计算棒分析结果也是不需要用户关心的。用户可以自定义的流程,就是传入RGB数据,和分析结果出来后画框(这是可选步骤,不一定非要画框)。结合我们第二篇文章,思路就清晰了,我们已经完成了摄像头的解码操作,得到了yuv数据,我们所作的操作就是转换成RGB数据,然后通过rknn_api接口塞给计算棒就可以了。这是我们的rga接口就派上了用场了,它可以将yuv数据转换成rgb数据(我这里测试的,实际上是转成bgr数据才正确)。
这里还有一点需要注意,传入的rgb数据并不是原长宽,考虑到分析的速度,一般都是对图片进行了压缩。比如说一个训练支持416*416数据的模型,原摄像头是1080*720(720P),那么得到720P的YUV数据后,需要将其缩放成416*416的rgb数据传入才可以正确分析。所以这步一定要确定你们训练的模型大小,然后针对性的缩放拉伸。rgb一般可以直接缩放成该大小的rgb数据,但是为了更好的识别现实中场景,减少因缩放产生的物体扭曲。我们应按整数比例缩放图片后,再进行冗余填充,这块可使用到opencv的copyMakeBorder函数。参考lettbox函数如下:
cv::Mat CV5Detect::letterbox(ffmpeg::RgaData &rData, int target_w, int target_h, int &wpad, int &hpad, float &scale)
{
int in_w = rData.width;
int in_h = rData.height;
int tar_w = target_w;
int tar_h = target_h;
float r = std::min(float(tar_h) / in_h, float(tar_w) / in_w);
int inside_w = round(in_w*r);
int inside_h = round(in_h*r);
int padd_w = tar_w - inside_w;
int padd_h = tar_h - inside_h;
wpad = padd_w;
hpad = padd_h;
scale = r;
cv::Mat src(in_h, in_w, CV_8UC3);
src.data = rData.data;
cv::Mat resize_img(inside_h, inside_w, CV_8UC3);
/// 如果宽高非4对齐,使用软缩(性能低)
if (inside_w % 4 != 0 || inside_h % 4 != 0)
{
cv::resize(src, resize_img, cv::Size(inside_w, inside_h));
}
else
{
ffmpeg::RgaData rgaDataOut;
rgaDataOut.type = ffmpeg::BGR24;
rgaDataOut.width = inside_w;
rgaDataOut.height = inside_h;
rgaDataOut.data = m_picData.get();
/// 通过rga进行缩放,性能高,不占cpu
if (!m_pPeg->transRga(rData, rgaDataOut))
{
errorf("enc transRga failed\n");
return resize_img;
}
resize_img.data = rgaDataOut.data;
}
// cv::imwrite("resize.jpg", resize_img);
padd_w = padd_w / 2;
padd_h = padd_h / 2;
int top = int(round(padd_h - 0.1));
int bottom = hpad - top;
int left = int(round(padd_w - 0.1));
int right = wpad - left;
/// 冗余填充,使图片在等比例缩放的条件下,符合传入计算棒的RGB图像大小
cv::copyMakeBorder(resize_img, resize_img, top, bottom, left, right, cv::BORDER_CONSTANT, cv::Scalar(114, 114, 114));
return resize_img;
}
对于一路摄像头AI识别,基本上可以做到全帧率识别的。也就是从解码-AI识别-显示,都是可以串行操作。但是对于同时多路识别,就不能串行了。需要将解码,AI,显示异步解开。同时降低帧率。
本篇就作为3399视频系列结束了,附件包提供自己封装的解码,AI,显示一套流程。AI识别我们是基于3399加1808的方案做的,如果是3399Pro的话,还需要少许改动。程序仅保证720P及以下分辨率显示及识别效果,码流类型H264,可针对摄像头进行配置。
程序使用方法:
程序下载后,将压缩包解压至3399的任意目录,运行run.sh即可。配置视频方法,编辑config/QtUi/video_channel.json文件。按照下图字段解释,配置相应字段即可。配置完后重启程序即可生效
{
"QtUiConfig" :
{
"channels" : --->数组,接入多路摄像头。最多8路720P
[
{
"camType" : 0,
"enable" : true, --->使能流,设置true,进行拉流解码操作
"enableAI" : true, --->使能,在插入计算棒的情况下,可进行AI识别
"ip" : "192.168.31.61", --->摄像头IP,可根据实际情况填写
"name" : "chan2", --->摄像头名称,自定义,多路情况下,名称不能重复
"nodeId" : "E024E47A524C45F8", --->此字段,会自动生成,建议删除,如果手动填写,确保不一样
"password" : "root12345", --->摄像头密码
"port" : 80,
"procted_zone" :
{
"points" : [],
"type" : ""
},
"profile" : "Profile_1",
"protocol" : "onvif",
"streamUrl" : "rtsp://admin:root12345@192.168.31.61:554/Streaming/Channels/101", --->摄像头rtsp流地址,此为海康示例,其它厂商流地址,自行确定填写
"user" : "admin", --->用户名
"widgetId" : --->播放窗口序列号
[
0
]
}
],
"display" : true --->true为显示QT界面,false不显示
}
}
建议接上显示屏,可以QT界面展示流界面及AI识别结果。可双击界面左下角,通道列表-全部通道,双击具体的通道。右侧窗口即可播放
二次开发接口及程序免费运行license请联系微信HardAndBetter获取,或者加入QQ群586166104讨论。
程序下载路径
3399视频AI分析demo-图像识别文档类资源-优快云下载
没有积分可进行百度网盘下载,路径如下:
https://pan.baidu.com/s/1zB7Ezpi4ONnVheRn1l84lA 提取码:8jjd