opencv rtsp 硬件解码

讨论使用opencv的reader

硬件解码的方案有太多种,如果使用ffmpeg硬件解码是最方便的,不方便的是把解码过后的GPU 拉到 CPU 上,再使用opencv的Mat 从cpu 上上载到gpu上,是不是多了两个过程,应该是直接从GPU mat 直接去处理, 最后一步再从GPU mat 上下载到cpu,render显示。

GPU 硬件解码是nv12 格式,我们为了显示和cpu使用直接转成了RGB或者BGR, 使用opencv再映射封装,最后又上载到cuda,这个过程很耗时间,而且不是必要的。

windows下使用cuda

经过实验,cv::cudacodec::createVideoReader 是可以拉取rtsp 流的,官方编译的可以读取rtsp,但是在文件流上出了问题,而且还有一个bug,就是在显示的时候,必须关闭一次窗口,才能显示后续的帧,而且还有一点,就是注意这个窗口必须是opengl 窗口,而且要打开这个窗口,而且在编译支持cuda的opencv时必须把opengl 勾选上,所以达不到产品化的要求,以下是测试代码:

#include <iostream>#include "opencv2/opencv_modules.hpp"#if defined(HAVE_OPENCV_CUDACODEC)#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/core/opengl.hpp>
#include <opencv2/cudacodec.hpp>
#include <opencv2/highgui.hpp>#if _DEBUG
#pragma comment(lib,"opencv_world460.lib")
#else 
#pragma comment(lib,"opencv_world460.lib")
#endif
int main()
{cv::cuda::printCudaDeviceInfo(cv::cuda::getDevice());int count = cv::cuda::getCudaEnabledDeviceCount();printf("GPU Device Count : %d \n", count);const std::string fname("rtsp://127.0.0.1/101-640.mkv"); //视频文件// const std::string fname("test_222.mp4"); //视频文件// cv::namedWindow("CPU", cv::WINDOW_NORMAL);cv::namedWindow("GPU", cv::WINDOW_OPENGL);cv::cuda::setGlDevice();cv::Mat frame;cv::VideoCapture reader(fname);cv::cuda::GpuMat d_frame;cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(fname);cv::TickMeter tm;std::vector<double> cpu_times;std::vector<double> gpu_times;int gpu_frame_count = 0, cpu_frame_count = 0;
#if 0for (;;){tm.reset(); tm.start();if (!reader.read(frame))break;tm.stop();cpu_times.push_back(tm.getTimeMilli());cpu_frame_count++;cv::imshow("CPU", frame);if (cv::waitKey(1) > 0)break;}
#endiffor (;;){tm.reset();tm.start();if (!d_reader->nextFrame(d_frame))break;tm.stop();//d_frame.step = d_frame.cols * d_frame.channels();//cv::cuda::GpuMat gpuMat_Temp = d_frame.clone();gpu_times.push_back(tm.getTimeMilli());gpu_frame_count++;if (gpu_frame_count > 2){cv::Mat test;d_frame.download(test);d_frame.release();// cv::cvtColor(test, test, cv::COLOR_BGRA2BGR);//cv::imwrite("./test1.jpg", test);cv::imshow("GPU", test);}if (cv::waitKey(1) > 0)break;}if (!cpu_times.empty() && !gpu_times.empty()){std::cout << std::endl << "Results:" << std::endl;std::sort(cpu_times.begin(), cpu_times.end());std::sort(gpu_times.begin(), gpu_times.end());double cpu_avg = std::accumulate(cpu_times.begin(), cpu_times.end(), 0.0) / cpu_times.size();double gpu_avg = std::accumulate(gpu_times.begin(), gpu_times.end(), 0.0) / gpu_times.size();std::cout << "CPU : Avg : " << cpu_avg << " ms FPS : " << 1000.0 / cpu_avg << " Frames " << cpu_frame_count << std::endl;std::cout << "GPU : Avg : " << gpu_avg << " ms FPS : " << 1000.0 / gpu_avg << " Frames " << gpu_frame_count << std::endl;}return 0;
}

经过release版本的测试,cuda硬件解码比cpu慢很多,我cpu是intel 13代 13700,速度很快,gpu是3060ti, 实际测试就是如此。
说明在windows下实际类里面解码的时候在cpu和gpu上转换的时间太多
在这里插入图片描述
    综上所述,必须使用更为简单的方法,放弃windows上的做法,放到linux上, ffmpeg硬件解码 然后映射到gpu mat上,至于解码ffmpeg 可以看我的其他文章,至于ffmpeg 编解码 nvidia 上官网也是有介绍的:
编译ffmpeg
    使用python和linux,使用python的作用是取消c++ 到python之间的内存共享,在windows上编译pynvcodec 会遇到各种问题,建议在linux 编译 pynvcodec,为什么不使用ffmpeg直接解码,因为:我们使用ffmpeg解码得到的YUV格式,我们只能在CPU下转化到RGB的色彩空间,缺少在GPU上进行全部转化的流程,因此我们使用vpf 来进行python上的视频处理,同时结束时可以直接转化成pytorch的张量来处理。

    VideoProcessingFramework(VPF)是NVIDIA开源的适用于Python的视频处理框架,可用于硬件加速条件下的视频编解码等处理类任务。同时对于Pytorch比较友好,能够将解析出来的图像数据直接转化成Tensor()的格式。以下为例子:

import PyNvCodec as nvc
import PytorchNvCodec as pnvc  while True:# Read data.# Amount doesn't really matter, will be updated later on during decode.bits = proc.stdout.read(read_size)if not len(bits):print("Can't read data from pipe")breakelse:rt += len(bits)# Decodeenc_packet = np.frombuffer(buffer=bits, dtype=np.uint8)pkt_data = nvc.PacketData()try:surf = nvdec.DecodeSurfaceFromPacket(enc_packet, pkt_data)    # 获取流的数据# Convert to planar RGBrgb_pln = to_rgb.run(surf)   # 转换到rgb_plnif rgb_pln.Empty():break# PROCESS YOUR TENSOR HERE.# THIS DUMMY PROCESSING JUST ADDS RANDOM ROTATION.src_tensor = surface_to_tensor(rgb_pln)  # 转化为Tensor(),数据存储在GPU中dst_tensor = T.RandomRotation(degrees=(-1, 1))(src_tensor)surface_rgb = tensor_to_surface(dst_tensor, gpu_id)# Convert back to NV12dst_surface = to_nv12.run(surface_rgb) # 再转换回码流if src_surface.Empty():break# Handle HW exceptions in simplest possible way by decoder respawnexcept nvc.HwResetException:nvdec = nvc.PyNvDecoder(w, h, f, c, g)continue

使用gstreamer

近来来opencv的下载是一个问题,动不动就下载出错,使用gstreamer 在windows下和ffmpeg 差不离,编译也比较麻烦,我们尽量在linux下编译

sudo apt-get update 
sudo apt-get install build-essential cmake git pkg-config 
sudo apt-get install libjpeg8-dev libtiff4-dev libjasper-dev libpng12-dev 
sudo apt-get install libgtk2.0-dev 
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev 
sudo apt-get install libatlas-base-dev gfortran 
//在opencv里面安装gstreamer插件 
sudo apt-get install gstreamer1.0-tools gstreamer1.0-alsa gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav 
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgstreamer-plugins-bad1.0-dev cd /home/opencv 
git clone https://github.com/opencv.git 
cd opencv 
git checkout 4.7.0 
cd /home/opcv 
nkdir build 
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D CUDA_GENERATION=Kepler .. 
make -j4 
sudo make install
int main()
{// std::cout << cv::getBuildInformation() << std::endl;using std::chrono::steady_clock;typedef std::chrono::milliseconds milliseconds_type;const int interval = 15;std::stringstream ss;std::string rtsp_url = "rtsp://127.0.0.1/101-640.mkv";size_t latency = 200;size_t frame_width = 1920;size_t frame_height = 1080;size_t framerate = 15;ss << "rtspsrc location=" << rtsp_url << " latency=" << latency << " ! application/x-rtp, media=video, encoding-name=H264 "<< "! rtph264depay ! video/x-h264, clock-rate=90000, width=" << frame_width << ", height=" << frame_height << ", framerate="<< framerate << "/1 ! nvv4l2decoder ! video/x-raw(memory:NVMM), width=" << frame_width << ", height=" << frame_height<< ", framerate=" << framerate << "/1 ! nvvideoconvert ! video/x-raw, format=BGRx ! videoconvert ! video/x-raw, format=BGR ! appsink";std::cout << ss.str() << std::endl;cv::VideoCapture cap = cv::VideoCapture(ss.str(), cv::CAP_GSTREAMER);if (!cap.isOpened()){std::cerr << "error to open camera." << std::endl;return -1;}std::cout << cv::getBuildInformation() << std::endl;cv::Mat frame;steady_clock::time_point start = steady_clock::now();size_t frame_idx = 0;while (1){bool ret = cap.read(frame);if (ret){// cv::imwrite("tmp.jpg", frame);++frame_idx;}if (frame_idx % interval == 0){steady_clock::time_point end = steady_clock::now();milliseconds_type span = std::chrono::duration_cast<milliseconds_type>(end - start);std::cout << "it took " << span.count() / frame_idx << " millisencods." << std::endl;start = end;}}return 0;
}

一点一点排除,在windows上很难复现很多代码,很多都是不稳当的做法,只能做做demo,完全产品化不了,我们目前稳定的做法,1 是使用live555 ,下拉 rtsp,ffmpeg 硬件解码,转成mat,转成gpumat,再转成mat。这个方案不断修改吧。等我更新。

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

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

相关文章

腾讯测试大佬分享4个关于 Python 函数(方法)的冷知识

关于参数标识 不知道大家在工作中有没有遇到一种情况&#xff0c;你的同事 A 写了一个方法给你调用&#xff0c;然后你调用时不知道该传什么参数&#xff0c;然后这个同事 A 还很 cao dan 的居然不加班&#xff01;你一脸茫然的看着这个方法&#xff0c;当你尝试传进去一个 ab…

使用pg_prewarm缓存PostgreSQL数据库表

pg_prewarm pg_prewarm 直接利用系统缓存的代码,对操作系统发出异步prefetch请求&#xff0c;在应用中&#xff0c;尤其在OLAP的情况下&#xff0c;对于大表的分析等等是非常耗费查询的时间的&#xff0c;而即使我们使用select table的方式&#xff0c;这张表也并不可能将所有…

后端整理(MySql)

1 事务 1.1 事务ACID原则 原子性&#xff08;Atomicity&#xff09; 事务的原子性指的是事务的操作&#xff0c;要么全部成功&#xff0c;要么全部失败回滚 一致性&#xff08;Consistency&#xff09; 事务的一致性是指事务必须使数据库从一个一致状态转变成另一个一致性…

hugging face下载数据集

开始直接执行这个&#xff0c;下载下来的图片打不开 git clone https://huggingface.co/datasets/diffusers/dog-example 解决办法&#xff1a; 安装git lfs 1. curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash 2. sudo apt…

会议OA系统会议管理模块开发思路(layui搭建)

目录 一.为什么要进行开发 1.开发目的 2.项目流程 A.发起会议请求过程 1.首先实现我们的多选下拉框功能&#xff01; 2.时间组件功能&#xff0c;并且提交我们新增加的会议内容 3.在进行发起会议编码时遇到的问题&#xff0c;BUG 3.1.有点时候js访问不到路径 3.2在增加…

Ctfshow web入门 JWT篇 web345-web350 详细题解 全

CTFshow JWT web345 先看题目&#xff0c;提示admin。 抓个包看看看。 好吧我不装了&#xff0c;其实我知道是JWT。直接开做。 在jwt.io转换后&#xff0c;发现不存在第三部分的签证&#xff0c;也就不需要知道密钥。 全称是JSON Web Token。 通俗地说&#xff0c;JWT的本质…

【知网检索】2023年金融,贸易和商业管理国际学术会议(FTBM2023)

随着经济全球化&#xff0c;贸易自由化的进程加快&#xff0c;我国经济对外开放程度不断加深&#xff0c;正在加快融入世界经济一体化当中。当今世界各国竞争过程中&#xff0c;金融、贸易以及商业形态已成为其关键与焦点竞争内容。 2023年金融、贸易和商业管理国际学术会议(F…

神经网络简单介绍

人工神经网络(artififial neural network) 简称神经网络&#xff0c;它是一种模仿生物神经网络结构和功能的非线性数学模型。 神经网络通过输入层接受原始特征信息&#xff0c;再通过隐藏层进行特征信息的加工和提取&#xff0c;最后通过输出层输出结果。 根据需要神经网络可以…

【1.1】Java微服务:初识微服务

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a; 微服务 ✨特色专栏&#xff1a; 知识分享 &#x…

使用Flutter的image_picker插件实现设备的相册的访问和拍照

文章目录 需求描述Flutter插件image_picker的介绍使用步骤1、添加依赖2、导入 例子完整的代码效果 总结 需求描述 在应用开发时&#xff0c;我们有很多场景要使用到更换图片的功能&#xff0c;即将原本的图像替换设置成其他的图像&#xff0c;从设备的相册或相机中选择图片或拍…

word里的页码问题

封面不需要页码怎么办 一份文档写完&#xff0c;如果需要页码&#xff0c;第一页是封面&#xff0c;封面不需要页码怎么办&#xff1f; 解决&#xff1a;打开页眉页脚&#xff0c;然后把首页不同勾选上&#xff0c;这一页就没有页码了。 目录页与正文页码格式不同怎么办 目录…

Istio 安全 授权管理AuthorizationPolicy

这个和cka考试里面的网络策略是类似的。它是可以实现更加细颗粒度限制的。 本质其实就是设置谁可以访问&#xff0c;谁不可以访问。默认命名空间是没有AuthorizationPolicy---允许所有的客户端访问。 这里是没有指定应用到谁上面去&#xff0c;有没有指定使用哪些客户端&#…

Mybatis引出的一系列问题-Mybatis缓存机制的探究

Mybatis 使用到了两种缓存&#xff1a;本地缓存&#xff08;local cache&#xff09;和二级缓存&#xff08;second level cache&#xff09;。 一级缓存默认是开启的&#xff0c;而且不能关闭&#xff0c;MyBatis的一些关键特性&#xff08;例如通过<association>和<…

Nginx学习教程(基础篇)

目录 一、Nginx安装 二、Nginx基本使用 2.1、目录结构 conf html logs sbin 2.2、基本运行原理 2.3、nginx.conf最小配置解析 worker_processes worker_connections include mime.types default_type application/octet-stream sendfile on keepalive_timeout…

eBay逆变器UL458检测报告

逆变器是把直流电能&#xff08;电池、蓄电瓶&#xff09;转变成交流电&#xff08;一般为220V,50Hz正弦波&#xff09;。它由逆变桥、控制逻辑和滤波电路组成。逆变器是一种DC to AC的变压器&#xff0c;它其实与转化器是一种电压逆变的过程。广泛适用于办公设备&#xff0c;生…

【MYSQL】DataGrip连接linux本地mysql失败:Connection refused

防火墙需要开放3306端口 sudo ufw allow 3306 要么就把防火墙关了&#xff1a; sudo ufw disablemysql开放连接 记住你的密码 ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password by 123456;修改配置文件 sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf这个…

Vue的 hash 模式与 history 模式

为了能够在改变视图的同时&#xff0c;不向后端发出网络请求。浏览器提供了 hash 模式与 history 模式。 而 vue 中的路由器就是利用了这两种模式&#xff0c;来实现前端路由的。 路由器的 hash 模式&#xff1a; 一、在 router 目录下的 index.js 文件中&#xff0c;通过 m…

什么是搜索引擎?2023 年搜索引擎如何运作?

目录 什么是搜索引擎&#xff1f;搜索引擎的原理什么是搜索引擎爬取&#xff1f;什么是搜索引擎索引&#xff1f;什么是搜索引擎检索?什么是搜索引擎排序&#xff1f; 搜索引擎的目的是什么&#xff1f;搜索引擎如何赚钱&#xff1f;搜索引擎如何建立索引?网页抓取文本处理建…

[Docker实现测试部署CI/CD----Jenkins集成相关服务器(3)]

目录 7、 Jenkins 集成 SonarQubeJenkins 中安装 SonarScanner下载移动修改配置文件 8、Jenkins配置SonarQube安装插件添加SonarQube添加 SonarScanner 9、Jenkins集成目标服务器 7、 Jenkins 集成 SonarQube Jenkins 中安装 SonarScanner SonarScanner 是一种代码扫描工具&am…

express学习笔记6 - 用户模块

新建router/user.js const express require(express) const routerexpress.Router() router.get(/login, function(req, res, next) {console.log(/user/login, req.body)res.json({code: 0,msg: 登录成功})})module.exportsrouter 在router/user.js引入并使用 const us…