Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >OpenCV调用海康威视等摄像头(处理rtsp视频流)方法以及,出现内存溢出(error while decoding)或者高延迟问题解决[通俗易懂]

OpenCV调用海康威视等摄像头(处理rtsp视频流)方法以及,出现内存溢出(error while decoding)或者高延迟问题解决[通俗易懂]

作者头像
全栈程序员站长
发布于 2022-11-02 07:49:01
发布于 2022-11-02 07:49:01
9.2K00
代码可运行
举报
运行总次数:0
代码可运行

博客已搬家,欢迎访问新居:http://lukeyalvin.site,主要涉及SLAM相关方向,目前知识积累尚浅,多多指教!

摄像头与电脑的连接

首先,你需要获得hikvision摄像头的密码以及用户名(不知道的可以去打客服电话进行咨询),这里不做介绍;

其次,将电脑的ip设置与hikvision同频段,一般来说,海康威视的ip为192.168.1.64,电脑设置如下:

最后,使用IE浏览器(其他可能不支持),输入ip:192.168.1.64并登陆

输入用户名和密码即可获取视频画面(可以观察到,视频有畸变)

使用python+openCV获取监控画面

在使用openCV获取监控画面,具体代码如下

url格式为:“rtsp://用户名(一般默认admin):密码@网络IP(海康威视一般为:192.168.1.64)/Streaming/Channels/1”

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2

url = "rtsp://admin:*******@192.168.1.64/Streaming/Channels/1"
cap = cv2.VideoCapture(url)
ret, frame = cap.read()
while ret:
	# 读取视频帧
    ret, frame = cap.read()
	# 显示视频帧
    cv2.imshow("frame", frame)
	#等候1ms,播放下一帧,或者按q键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

#释放视频流
cap.release()
#关闭所有窗口
cv2.destroyAllWindows()

输出画面默认是1080P的高清画面,我们可以写一个resize方法,等比例缩为720P的画面,代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def img_resize(image):
    height, width = image.shape[0], image.shape[1]
    # 设置新的图片分辨率框架 640x369 1280×720 1920×1080
    width_new = 1280
    height_new = 720
    # 判断图片的长宽比率
    if width / height >= width_new / height_new:
        img_new = cv2.resize(image, (width_new, int(height * width_new / width)))
    else:
        img_new = cv2.resize(image, (int(width * height_new / height), height_new))
    return img_new

然后在显示之前调用该函数进行处理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 	# 读取视频帧
    ret, frame = cap.read()
    # 显示视频帧
    img_new = img_resize(frame)
    cv2.imshow("frame", img_new)
    #等候1ms,播放下一帧,或者按q键退出

实现效果如下:

使用模型处理图像发生内存溢出与高延迟问题解决

我的毕业设计主要使用YOLOv3+deep-sort实现目标检测与实时跟踪,在这里不做详细的理论介绍,以及具体代码的实现,后面会有相关的博客进行专门系统性的讲述,这里主要讲一种处理内存溢出或者高延迟问题的有效解决方案,在使用模型处理图像之后,每次将处理的画面显示出来,只有三秒的时间(下面为处理后的画面)

然后随后就会发生内存溢出的现象,报错内容如下:

但是,当我使用电脑默认的摄像头,就发现非常的流畅,没有内存溢出的现象,这就十分的诡异,然后我猜测是不是因调用rtsp视频流或取得没帧的分辨率多大,导致检测速度过慢,引起传入帧数与处理帧数不对等引起的内存的溢出,但是我尝试减小了分辨率,甚至于获取的帧图像大小比电脑内置摄像头还有小,结果没有任何的改善;

解决这个问题也寻求网上很多解决方案,以下具体结合各位前辈做一下总结:

使用多线程解决:

首先,需要思考,为什么会造成这种现象?有大佬给出这样的解决方案:

FFMPEG Lib对在rtsp协议中的H264 videos不支持?

维基百科: 实时流协议(Real Time Streaming Protocol,RTSP)是一种网络应用协议,专为娱乐和通信系统的使用,以控制流媒体服务器。该协议用于创建和控制终端之间的媒体会话。媒体服务器的客户端发布VCR命令,例如播放,录制和暂停,以便于实时控制从服务器到客户端(视频点播)或从客户端到服务器(语音录音)的媒体流。

FFmpeg 是一个开放源代码的自由软件,可以运行音频和视频多种格式的录影、转换、流功能[1],包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库,以及libavformat——一个音频与视频格式转换库。 这个项目最初是由法国程序员法布里斯·贝拉(Fabrice Bellard)发起的,而现在是由迈克尔·尼德梅尔(Michael Niedermayer)在进行维护。许多FFmpeg的开发者同时也是MPlayer项目的成员,FFmpeg在MPlayer项目中是被设计为服务器版本进行开发。 2011年3月13日,FFmpeg部分开发人士决定另组Libav,同时制定了一套关于项目继续发展和维护的规则

不管怎么说,就是不支持的意思,就是无法实现,我尝试了这位博主的方法,然而并没有解决的问题,效果还是原来的效果,还是三秒,真就是三秒啊~

参考博客:解决Python OpenCV 读取IP摄像头(RTSP等)出现error while decoding的问题

博主代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2
import queue
import time
import threading
q=queue.Queue()
def Receive():
print("start Reveive")
cap = cv2.VideoCapture("rtsp://admin:admin_123@172.0.0.0")
ret, frame = cap.read()
q.put(frame)
while ret:
ret, frame = cap.read()
q.put(frame)
def Display():
print("Start Displaying")
while True:
if q.empty() !=True:
frame=q.get()
cv2.imshow("frame1", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if __name__=='__main__':
p1=threading.Thread(target=Receive)
p2 = threading.Thread(target=Display)
p1.start()
p2.start()

使用多进程

其实造成内存溢出,主要是由于利用opencv程序调取rtsp视频流时,处理程序要消耗的CPU时间过于长,VideoCapture的read是按帧读取所导致的,解决问题点在于把读取视频和处理视频分开,这样就可以消除因处理图片所导致的延迟。

其实使用多线程当然也可以实现两个动作分开进行,但是为什么几乎没有任何的效果呢?

原因主要是GIL的存在:

维基百科: 全局解释器(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。[1]即便在多核心处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程。常见的使用 GIL 的解释器有CPythonRuby MRI。 在Windows上为Win thread,完全由操作系统调度线程的执行。一个Python解释器进程内有一个主线程,以及多个用户程序的执行线程。即便使用多核心CPU平台,由于GIL的存在,也将禁止多线程的并行执行。 Python解释器进程内的多线程是以协作多任务方式执行。当一个线程遇到I/O任务时,将释放GIL。计算密集型(CPU-bound)的线程在执行大约100次解释器的计步(ticks)时,将释放GIL。计步(ticks)可粗略看作Python虚拟机的指令。计步实际上与时间片长度无关。可以通过sys.setcheckinterval()设置计步长度。

因此,选择使用多进程

  • 然后要考虑怎样在两个进程中传参的问题:
    • multiprocessing中有Quaue、SimpleQuaue等进程间传参类,还有Manager这个大管家。
    • Quaue这一类都是严格的数据结构队列类型
    • Manager比较特殊,它提供了可以在进程间传递的列表、字典等python原生类型
  • 还要考虑怎样才能达到处理进程可以在读取进程中得到最新的一帧:
    • 其实VideoCapture是一个天生的队列,先进先出。如果要达到实时获得最新帧的目的,就需要栈来存储视频帧,而不是队列。
    • 这样的话,Quaue这一大类就都没有可能了,肯定不能用它来传参。
    • 提到栈突然想到了python的列表,它的append和pop操作完全可以当”不严格“的栈来用。所以顺理成章地multiprocessing.Manager.list就是最好的进程间传参类型。
  • 再就是传参栈自动清理的问题,压栈频率肯定是要比出栈频率高的,时间一长就会在栈中积累大量无法出栈的视频帧,会导致程序崩溃,这就需要有一个自动清理机制:
    • 设置一个传参栈容量,每当达到这个容量就直接把栈清空,再利用gc库手动发起一次python垃圾回收。这样就不会导致严重的内存溢出和程序崩溃。

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import os
import cv2
import gc
from multiprocessing import Process, Manager
# 向共享缓冲栈中写入数据:
def write(stack, cam, top: int) -> None:
""" :param cam: 摄像头参数 :param stack: Manager.list对象 :param top: 缓冲栈容量 :return: None """
print('Process to write: %s' % os.getpid())
cap = cv2.VideoCapture(cam)
while True:
_, img = cap.read()
if _:
stack.append(img)
# 每到一定容量清空一次缓冲栈
# 利用gc库,手动清理内存垃圾,防止内存溢出
if len(stack) >= top:
del stack[:]
gc.collect()
# 在缓冲栈中读取数据:
def read(stack) -> None:
print('Process to read: %s' % os.getpid())
while True:
if len(stack) != 0:
value = stack.pop()
# 对获取的视频帧分辨率重处理
img_new = img_resize(value)
# 使用yolo模型处理视频帧
yolo_img = yolo_deal(img_new)
# 显示处理后的视频帧
cv2.imshow("img", yolo_img)
# 将处理的视频帧存放在文件夹里
save_img(yolo_img)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
if __name__ == '__main__':
# 父进程创建缓冲栈,并传给各个子进程:
q = Manager().list()
pw = Process(target=write, args=(q, url, 100))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 启动子进程pr,读取:
pr.start()
# 等待pr结束:
pr.join()
# pw进程里是死循环,无法等待其结束,只能强行终止:
pw.terminate()

实时画面如下:

存入视频帧:

nice! 项目实现后续系统讲述…

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/180763.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python 调用海康威视 摄像头 显示预览画面
支持 RTSP(Runtime Stream Protocol)协议的摄像头可以很方便地用 opencv i调用
为为为什么
2024/05/23
1.6K0
opencv之打开摄像头、边缘检测
许多工业相机或某些视频I / O设备不为操作系统提供标准的驱动程序接口。因此,您不能在这些设备上使用VideoCapture或VideoWriter。
全栈程序员站长
2022/07/23
3.6K0
opencv之打开摄像头、边缘检测
Python基于opencv调用摄像头获取个人图片的实现方法
接触图像领域的应该对于opencv都不会感到陌生,这个应该算是功能十分强劲的一个算法库了,当然了,使用起来也是很方便的,之前使用Windows7的时候出现多该库难以安装成功的情况,现在这个问题就不存在了,需要安装包的话可以去我的资源中下载使用,使用pip安装方式十分地便捷。
matinal
2020/11/27
1.8K0
Python基于opencv调用摄像头获取个人图片的实现方法
如何使用OpenCV在Python中访问IP摄像头
首先,必须找出网址流是什么。通过在构造函数中提供摄像机的网址流,可以在OpenCV中访问IP摄像机cv2.VideoCapture。可以使用某些网络扫描实用程序(例如在linux上的arp-scan)找到摄像机的IP地址。网址进一步的细节,如Protocol,Credentials和Channel应该可以在相机说明书或软件/手机应用程序中找到。我们通过在网络上搜索相机的型号来找到相机的网址流。
小白学视觉
2020/09/14
7.2K0
OpenCV 获取 RTSP 摄像头视频流保存至本地
Java OpenCV 是一个强大的开源计算机视觉库,它提供了丰富的图像处理和分析功能,越来越多的应用需要使用摄像头来获取实时视频流进行处理和分析。
默存
2024/05/20
6340
OpenCV 获取 RTSP 摄像头视频流保存至本地
OpenCV调用摄像头
python:python3.6 摄像头:网络摄像头 Python库:openCV
py3study
2020/01/02
1.8K0
使用Opencv-python库读取图像、本地视频和摄像头实时数据
Python中使用OpenCV读取图像、本地视频和摄像头数据很简单, 首先需要安装Python,然后安装Opencv-python库
ccf19881030
2024/05/24
1.7K0
使用Opencv-python库读取图像、本地视频和摄像头实时数据
OpenCV调用USB摄像头/相机,并解决1080p下的延迟卡顿问题(附Python代码)
摄像头成功加载出来,但是默认分辨率太低(我的相机支持的是1080p),通过如下代码设置分辨率和帧率:
小黑鸭
2023/10/16
3.8K0
使用OpenCV调用摄像头,显示图片,获取视频并保存
友情链接:https://blog.csdn.net/u012348774/article/details/78255130
种花家的奋斗兔
2020/11/13
4.2K0
opencv读取摄像头和视频数据
淼学派对
2023/10/14
6080
opencv(4.5.3)-python(三)--视频入门
通常情况下,我们必须用摄像机来捕获实时流。OpenCV提供了一个非常简单的接口来做到这一点。让我们从摄像头(我使用的是笔记本电脑上的内置网络摄像头)捕捉一段视频,将其转换成灰度视频并显示出来。只是一个简单的任务就可以开始了。
用户9875047
2022/07/04
9860
基于Aidlux平台实现ONNX Runtime部署-水果分类-摄像头和视频
连接Aidlux后,使用jupyter notebook --allow-root进行Aidlux平台联系的jupyter notebook安装配置环境:
用户10686717
2023/08/07
3500
视频抽帧实践---openCV和decord视频编解码
剪辑平台中需要处理大量的视频,对视频内容的理解,离不开对视频的降维操作,一般流程是进行抽帧。抽帧操作是很多视频处理的第一步,也是基础数据的一步,大量算法模型离不开帧数据的训练,而高质量的视频,它的fps(每秒帧数)很大,这就造成了处理高清视频时,抽帧速度会成为整个视频处理的瓶颈,本文将对比目前主流的两个视频读取库, openCV和decord进行对比。
后厂村鹅厂
2022/08/11
5.1K0
保存rtsp视频流
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/02
2.3K0
多线程读取IP摄像头(Python)
在深度学习时代(这么说也不为过)的今天,我们做各种视觉任务时候都会想到使用深度学习,但是大家也都知道深度学习的模型如果想要使用的话,设备必须得有,虽然各种各样的量化策略和剪枝策略大大加速了模型的推理能力,但是实时的话在低配电脑还是不可用! 但是实际中有些视觉任务不怎么依赖实时性,我们只需要保证1s处理一帧图片就可以了,或者几十秒处理一帧也可以。那么这种处理策略怎么处理呢?特别对于IP摄像头,它是以数据流的形式传输,因此当其帧率较高时,本地处理程序会处理不过来,导致卡帧(延时)和程序卡死!我们一起来看看吧!
深度学习与Python
2019/07/23
2.6K0
百万点赞怎么来?Python批量制作抖音的卡点视频原来这么简单!
玩抖音的朋友都应该知道,最近「卡点视频」简直不要太火。抖音上很多大神也出了剪辑各种卡点视频的教程。
一墨编程学习
2019/07/18
2.8K0
百万点赞怎么来?Python批量制作抖音的卡点视频原来这么简单!
关于OpenCV for Python入门-图片和摄像头显示
OpenCV和Python结合的学习资料不多,网上的资料更是鱼目混杂,推荐大家OpenCV官方教程中文版 for Python,建议自行下载。
python与大数据分析
2022/04/02
1.5K0
关于OpenCV for Python入门-图片和摄像头显示
使用Python+Opencv从摄像头逐帧读取图片保存在本地
今天测试的时候,遇到了一个问题,测试需求是,需要把摄像头拍摄的实时视频逐帧率保存下来。经过查阅资料以及网友帮助,目前已经完成。记录下来希望可以帮助有需要的朋友。1、思路使用Python+Opencv,从摄像头的实时视频流中逐帧读取图片,保存到本地2、工具安装Python安装Opencv3、分类目前测试的过程中遇到了三种类型的摄像头数据读取,分别是:USB普通摄像机:直接使用Python+Opencv,进行数据采集self.cap = cv2.VideoCapture(0);0是本地摄像头USB工业摄像头:使
虫无涯
2023/01/17
2K0
一段蛋疼的代码:超不清视频播放器
今天分享的这段代码,看起来没啥实际用处,而且有些反潮流,因为现如今大家看视频都追求更高分辨率的超清画质,而我们这个,是一个“超不清”的视频播放器:
Crossin先生
2018/12/17
8700
OpenCV 标定摄像头(Python 版本代码,视频中标定,亲测可用)
P=[fx0cx0fycy001] P = \begin{bmatrix} f_{x} & 0 & c_{x} \\ 0 & f_{y} & c_{y}\\ 0 & 0 & 1 \end{bmatrix} P=⎣⎡​fx​00​0fy​0​cx​cy​1​⎦⎤​
Frank909
2019/01/28
3.9K0
OpenCV 标定摄像头(Python 版本代码,视频中标定,亲测可用)
推荐阅读
相关推荐
Python 调用海康威视 摄像头 显示预览画面
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验