用Python访问视频数据
问题
我想知道怎么用Python从流式视频中获取一小部分帧,并对它们进行处理?有没有现成的库可以用,还是我得自己写整个项目?
技术规格
操作系统:Linux
连接方式:CAT-5以太网
摄像头:dlink DCS-930L
介绍
我之前问过一个问题,但因为不够清楚被关闭了。
现在我重新发帖,提供了更多细节,如果还有不清楚的地方,请随意编辑或留言。
背景
我有一台dlink DCS-930L摄像头,它通过直接的cat5连接到我的Linux电脑。我给它分配了一个静态IP地址,一切都运行得很好。
当我打开网页浏览器,连接到这个静态IP地址(比如登录192.168.0.20)时,摄像头可以实时正常工作。
这样做是为了确认我的摄像头正常工作,并且以太网连接建立得正确。
现在,我需要对从摄像头通过以太网接收到的视频帧进行一些图像处理。
我不想再通过网页浏览器来显示视频,而是想用Python来读取这些帧。
换句话说,假设摄像头每秒产生30帧,每帧的大小是某个特定的尺寸(例如1920x1080像素)。
我只想用Python开始读取这些帧。我不在乎错过一些帧,也不介意处理速度慢。即使我每几秒处理一帧,我也觉得可以。
因为视频就是一系列图像(在这个例子中是每秒30张图像),我想用Python读取这些图像,然后进行我需要的处理。
如果这些图像保存在电脑上,我可以用Python打开它们并开始处理。但在这种情况下,图像是流式传输的,我只想知道怎么才能采样这些图像(也许每隔几秒取一张),并用Python进行一些处理?
如果我的问题还是不清楚,请告诉我,我会尽量解释得更清楚。
谢谢,
--Rudy
2 个回答
我对dlink DCS-30的具体工作原理不是很了解,不过我有一个早期型号的相机,dlink DCS-20,我当时也有类似的目标,所以你可以参考我DCS-20的解决方案,或者其中的一部分,来解决DCS-30的问题。
关键在于解析内置网页浏览器提供的HTML内容。
使用外部模块,比如PIL和BeautifulSoup,可以让解决方案变得更简单。
假设你的相机IP是192.168.0.20,并且你通过网页管理设置了一个用户登录,用户名是user1,密码是pw1,下面就是解决方案的核心部分:
from StringIO import StringIO
import requests
from PIL import Image
from bs4 import BeautifulSoup
DCS_IP = "192.168.0.20"
userauth = ('user1', 'pw1')
snapurl = "http://" + DCS_IP + "/top.htm"
r = requests.get(snapurl, auth=userauth)
soup = BeautifulSoup(r.content)
# There are several <img> tags in page, so use border=0 attribute of
# objective <img> to distinguish it
imgtag = soup.find_all("img", attrs={'border':0})
imgsrc = BeautifulSoup(str(imgtag[0])).img['src']
imgurl = "http://" + DCS_IP + "/" + imgsrc
img = requests.get(imgurl, auth=userauth)
i = Image.open(StringIO(img.content))
i.save("snapshot.png")
一旦你获取了图像(i),你可以用PIL进一步处理,或者之后使用ffmpeg,比如把得到的图像集合拼接成一个延时视频。
希望这对你有帮助。
根据说明书,这款摄像头通过一个Java小程序来传输视频,所以如果你想用Python来访问它,就得先了解一下它的服务器协议,这可能会有点难。
不过,它确实有一个选项,可以把图片推送到一个FTP服务器(在第34页),所以如果你在你的Linux电脑上安装了vsftpd,你可以告诉摄像头把图片推送到那里,速度可能达到每秒4帧。关于如何在Ubuntu上设置vsftpd的说明可以在这里找到,其他版本的Linux设置也差不多(我记得Fedora的设置可能稍微简单一点,但那是很多年前的事了)。
你需要在/etc/vsftpd.conf
文件中启用上传功能,添加这一行write_enable=YES
。处理上传的方式有很多,最简单的方式是让摄像头用你的用户账号登录,这样它就会把图片放到你的主目录里(或者你在摄像头配置中指定的路径)。
这样你就可以正常打开这些图片了,比如用PIL库。
如果你不想设置文件服务器,你可以尝试直接用urllib2来抓取数据,关于如何处理登录的内容可以参考这个页面。通过尝试抓取数据,你有可能提取到视频流,但我觉得使用FTP的方式会简单很多。