如何使用OpenCV(Python)捕捉视频流

10 投票
1 回答
52928 浏览
提问于 2025-05-01 00:53

我想用Python和OpenCV处理来自IP摄像头的mms视频流,但我对这个摄像头没有控制权(它是一个交通监控摄像头)。

这个视频流可以通过mms或mmst协议获取 -

mms://194.90.203.111/cam2

在VLC和Windows Media Player上都能播放。

mmst://194.90.203.111/cam2

但在VLC上才能播放。我尝试用FFmpeg和VLC把协议改成HTTP来重新推流,但没有成功。

根据我的理解,mms协议是用Windows Media Video来编码这个流的。我试着在URI后面加上'.mjpeg',但也没用。我还没找到OpenCV支持哪些类型的视频流。

这是我的代码 -

import cv2, platform
#import numpy as np

cam = "mms://194.90.203.111/cam2"
#cam = 0 # Use  local webcam.

cap = cv2.VideoCapture(cam)
if not cap:
    print("!!! Failed VideoCapture: invalid parameter!")

while(True):
    # Capture frame-by-frame
    ret, current_frame = cap.read()
    if type(current_frame) == type(None):
        print("!!! Couldn't read frame!")
        break

    # Display the resulting frame
    cv2.imshow('frame',current_frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# release the capture
cap.release()
cv2.destroyAllWindows()

我漏掉了什么呢?OpenCV能捕捉到什么类型的视频流?有没有不需要改变协议或转码的优雅解决方案?

谢谢!

Python版本是2.7.8,OpenCV版本是2.4.9,都是x86架构,运行在Win7 x64上。

暂无标签

1 个回答

11

这个问题的解决方案是使用FFmpeg和FFserver。需要注意的是,FFserver只能在Linux系统上运行。

这个解决方案使用了来自这里的Python代码,正如Ryan所建议的。

整个流程如下:

  • 首先启动FFserver的后台进程,使用你想要的配置(在这个例子中是mjpeg)。
  • FFmpeg的输入是mmst流,输出流到本地计算机。
  • 运行Python脚本,打开本地流并逐帧解码。

运行FFserver

ffserver -d -f /etc/ffserver.conf

在第二个终端运行FFmpeg

ffmpeg -i mmst://194.90.203.111/cam2 http://localhost:8090/cam2.ffm

Python代码。在这个例子中,代码会打开一个窗口,显示视频流。

import cv2, platform
import numpy as np
import urllib
import os

cam2 = "http://localhost:8090/cam2.mjpeg"

stream=urllib.urlopen(cam2)
bytes=''
while True:
    # to read mjpeg frame -
    bytes+=stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a!=-1 and b!=-1:
        jpg = bytes[a:b+2]
        bytes= bytes[b+2:]
    frame = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.CV_LOAD_IMAGE_COLOR)
    # we now have frame stored in frame.

    cv2.imshow('cam2',frame)

    # Press 'q' to quit 
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

ffserver.config -

Port 8090
BindAddress 0.0.0.0
MaxClients 10
MaxBandWidth 50000
CustomLog -
#NoDaemon

<Feed cam2.ffm>
    File /tmp/cam2.ffm
    FileMaxSize 1G
    ACL allow 127.0.0.1
    ACL allow localhost
</Feed>
<Stream cam2.mjpeg>
    Feed cam2.ffm
    Format mpjpeg
    VideoFrameRate 25
    VideoBitRate 10240
    VideoBufferSize 20480
    VideoSize 320x240
    VideoQMin 3
    VideoQMax 31
    NoAudio
    Strict -1
</Stream>
<Stream stat.html>
    Format status
    # Only allow local people to get the status
    ACL allow localhost
    ACL allow 192.168.0.0 192.168.255.255
</Stream>
<Redirect index.html>
    URL http://www.ffmpeg.org/
</Redirect>

需要注意的是,这个ffserver.config还需要进一步调整,但它们的效果相当不错,生成的画面与源头非常接近,只会有一点点画面卡顿。

撰写回答