在 Python 中从 RTSP 流中读取帧
Posted
技术标签:
【中文标题】在 Python 中从 RTSP 流中读取帧【英文标题】:Read Frames from RTSP Stream in Python 【发布时间】:2013-07-31 03:54:53 【问题描述】:我最近设置了一个 Raspberry Pi 相机,并通过 RTSP 流式传输帧。虽然它可能不是完全必要的,但这是我正在使用广播视频的命令:
raspivid -o - -t 0 -w 1280 -h 800 |cvlc -vvv stream:///dev/stdin --sout '#rtpsdp=rtsp://:8554/output.h264' :demux=h264
这可以完美地流式传输视频。
我现在想做的是用 Python 解析这个流并单独读取每一帧。我想做一些用于监视目的的运动检测。
我完全不知道从哪里开始这项任务。谁能指点我一个好的教程?如果这无法通过 Python 实现,我可以使用哪些工具/语言来实现?
【问题讨论】:
看这里:superuser.com/questions/225367/… ...似乎连 vlc 都能做到这一点.. 【参考方案1】:使用“depu”列出的相同方法对我来说非常有效。 我只是用实际相机的“RTSP URL”替换了“视频文件”。 下面的示例适用于 AXIS IP 摄像机。 (这在以前版本的 OpenCV 中暂时不起作用) 适用于 OpenCV 3.4.1 Windows 10)
import cv2
cap = cv2.VideoCapture("rtsp://root:pass@192.168.0.91:554/axis-media/media.amp")
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow('frame', frame)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
【讨论】:
这几乎对我有用。我必须在 URL 的末尾附加一个分辨率查询参数,rtsp://user@pass@192.168.0.19/axis-media/media.amp?resolution=1280x720。我在 Ubuntu 18.04 上使用 OpenCV 4.1.2,摄像头是 Axis M5525-E。【参考方案2】:有点骇人听闻的解决方案,但您可以使用VLC python bindings(您可以使用pip install python-vlc
安装它)并播放流:
import vlc
player=vlc.MediaPlayer('rtsp://:8554/output.h264')
player.play()
然后每隔一秒左右拍一张快照:
while 1:
time.sleep(1)
player.video_take_snapshot(0, '.snapshot.tmp.png', 0, 0)
然后您可以使用SimpleCV 或其他东西进行处理(只需将图像文件'.snapshot.tmp.png'
加载到您的处理库中)。
【讨论】:
如何使用.snapshot.tmp.png
文件?
@ShaiM。与使用任何其他 PNG 文件的方式相同
可以和ubuntu服务器一起使用吗?
如果你安装了库,可能。试试看
顺便说一句,你能在这里看到我的问题吗:***.com/questions/48620863/… 谢谢【参考方案3】:
使用opencv
video=cv2.VideoCapture("rtsp url")
然后您可以捕获帧。阅读openCV文档访问:https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_video_display/py_video_display.html
【讨论】:
【参考方案4】:根据流类型,您可能可以看看这个项目以获得一些想法。
https://code.google.com/p/python-mjpeg-over-rtsp-client/
如果您想成为超级专业人士,可以使用 http://opencv.org/(我相信 Python 模块可用)之类的东西来处理运动检测。
【讨论】:
【参考方案5】:这里还有一个选项
这比其他答案复杂得多。 :-O
但是通过这种方式,只需一个连接到摄像头,您就可以将相同的流同时“分叉”到多个多进程、屏幕、重播为多播、写入磁盘等。
.. 当然,以防万一您需要类似的东西(否则您更喜欢较早的答案)
让我们创建两个独立的python程序:
(1)服务器程序(rtsp连接、解码)server.py
(2) 客户端程序(从共享内存中读取帧)client.py
服务器必须在客户端之前启动,即
python3 server.py
然后在另一个终端:
python3 client.py
代码如下:
(1) server.py
import time
from valkka.core import *
# YUV => RGB interpolation to the small size is done each 1000 milliseconds and passed on to the shmem ringbuffer
image_interval=1000
# define rgb image dimensions
width =1920//4
height =1080//4
# posix shared memory: identification tag and size of the ring buffer
shmem_name ="cam_example"
shmem_buffers =10
shmem_filter =RGBShmemFrameFilter(shmem_name, shmem_buffers, width, height)
sws_filter =SwScaleFrameFilter("sws_filter", width, height, shmem_filter)
interval_filter =TimeIntervalFrameFilter("interval_filter", image_interval, sws_filter)
avthread =AVThread("avthread",interval_filter)
av_in_filter =avthread.getFrameFilter()
livethread =LiveThread("livethread")
ctx =LiveConnectionContext(LiveConnectionType_rtsp, "rtsp://user:password@192.168.x.x", 1, av_in_filter)
avthread.startCall()
livethread.startCall()
avthread.decodingOnCall()
livethread.registerStreamCall(ctx)
livethread.playStreamCall(ctx)
# all those threads are written in cpp and they are running in the
# background. Sleep for 20 seconds - or do something else while
# the cpp threads are running and streaming video
time.sleep(20)
# stop threads
livethread.stopCall()
avthread.stopCall()
print("bye")
(2) client.py
import cv2
from valkka.api2 import ShmemRGBClient
width =1920//4
height =1080//4
# This identifies posix shared memory - must be same as in the server side
shmem_name ="cam_example"
# Size of the shmem ringbuffer - must be same as in the server side
shmem_buffers =10
client=ShmemRGBClient(
name =shmem_name,
n_ringbuffer =shmem_buffers,
width =width,
height =height,
mstimeout =1000, # client timeouts if nothing has been received in 1000 milliseconds
verbose =False
)
while True:
index, isize = client.pull()
if (index==None):
print("timeout")
else:
data =client.shmem_list[index][0:isize]
img =data.reshape((height,width,3))
img =cv2.GaussianBlur(img, (21, 21), 0)
cv2.imshow("valkka_opencv_demo",img)
cv2.waitKey(1)
如果您有兴趣,请在https://elsampsa.github.io/valkka-examples/ 中查看更多信息
【讨论】:
【参考方案6】:您可以使用 python 和 OpenCV 从视频中读取帧。下面是示例代码。适用于 python 和 opencv2 版本。
import cv2
import os
#Below code will capture the video frames and will sve it a folder (in current working directory)
dirname = 'myfolder'
#video path
cap = cv2.VideoCapture("your rtsp url")
count = 0
while(cap.isOpened()):
ret, frame = cap.read()
if not ret:
break
else:
cv2.imshow('frame', frame)
#The received "frame" will be saved. Or you can manipulate "frame" as per your needs.
name = "rec_frame"+str(count)+".jpg"
cv2.imwrite(os.path.join(dirname,name), frame)
count += 1
if cv2.waitKey(20) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
【讨论】:
唉,这里没有涉及到困难的部分(从 RTSP 流中读取帧)以上是关于在 Python 中从 RTSP 流中读取帧的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Spark 结构化流中的 Cassandra 等外部存储读取 Kafka 和查询?
在 PHP 中从 /Filter /FlateDecode PDF 流中提取数据
带有 Gstreamer 流的 OpenCV 具有延迟、缓慢和伪影