Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何解析来自ip摄像机的mjpeg http流?_Python_Opencv_Live Streaming_Ip Camera_Mjpeg - Fatal编程技术网

Python 如何解析来自ip摄像机的mjpeg http流?

Python 如何解析来自ip摄像机的mjpeg http流?,python,opencv,live-streaming,ip-camera,mjpeg,Python,Opencv,Live Streaming,Ip Camera,Mjpeg,下面给出了从IP摄像机获取实时流的代码 from cv2 import * from cv2 import cv import urllib import numpy as np k=0 capture=cv.CaptureFromFile("http://IPADDRESS of the camera/axis-cgi/mjpg/video.cgi") namedWindow("Display",1) while True: frame=cv.QueryFrame(capture)

下面给出了从IP摄像机获取实时流的代码

from cv2 import *
from cv2 import cv
import urllib
import numpy as np
k=0
capture=cv.CaptureFromFile("http://IPADDRESS of the camera/axis-cgi/mjpg/video.cgi")
namedWindow("Display",1)

while True:
    frame=cv.QueryFrame(capture)
    if frame is None:
        print 'Cam not found'
        break
    else:
        cv.ShowImage("Display", frame)
    if k==0x1b:
        print 'Esc. Exiting'
        break
在运行代码时,我得到的输出是:

Cam not found
我哪里做错了?还有,为什么这里没有框架?转换有什么问题吗

import cv2
import urllib 
import numpy as np

stream = urllib.urlopen('http://localhost:8080/frame.mjpg')
bytes = ''
while True:
    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:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)   
编辑(解释) <>我刚才看到你提到你有C++代码在工作,如果是这样的话,你的相机也可以在Python中工作。上面的代码在不依赖opencv的情况下手动解析mjpeg流,因为在我的一些项目中,无论我做了什么(c++,python),opencv都不会打开url

http上的Mjpeg是multipart/x-mixed-replace,带有边界帧信息,jpeg数据仅以二进制格式发送。因此,您实际上不需要关心http协议头。所有jpeg帧都以标记
0xff 0xd8
开始,以
0xff 0xd9
结束。因此,上面的代码从http流中提取这样的帧并逐个解码。如下图所示

...(http)
0xff 0xd8      --|
[jpeg data]      |--this part is extracted and decoded
0xff 0xd9      --|
...(http)
0xff 0xd8      --|
[jpeg data]      |--this part is extracted and decoded
0xff 0xd9      --|
...(http)
编辑2(从mjpg文件读取) 关于保存文件的问题,是的,可以使用相同的方法直接保存并重新打开文件,只需进行很小的修改。例如,您可以执行
curlhttp://IPCAM >输出.mjpg
然后更改行
stream=urllib.urlopen('http://localhost:8080/frame.mjpg)
这样代码就变成了

import cv2
import urllib 
import numpy as np

stream = open('output.mjpg', 'rb')
bytes = ''
while True:
    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:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)   
当然,您正在保存大量冗余的http头,您可能希望删除这些头。或者,如果您有额外的cpu能力,可能只需要先编码到h264。但是,如果相机正在向http头帧添加一些元数据,例如通道、时间戳等,那么保留它们可能会很有用

编辑3(tkinter接口)
首先,请注意,您应该首先尝试直接使用OpenCV的视频捕获功能,例如
cv2.VideoCapture('http://localhost:8080/frame.mjpg)

这对我来说很好:

import cv2
cap = cv2.VideoCapture('http://localhost:8080/frame.mjpg')

while True:
  ret, frame = cap.read()
  cv2.imshow('Video', frame)

  if cv2.waitKey(1) == 27:
    exit(0)
无论如何,这里是Zaw Lin移植到OpenCV 3的解决方案(唯一的变化是
cv2.CV\u LOAD\u IMAGE\u COLOR
cv2.IMREAD\u COLOR
和Python 3(字符串与字节处理的变化加上urllib):


下面是一个使用Python3requests模块而不是urllib的答案

不使用urllib的原因是它无法正确解释像
http://user:pass@IP地址:端口

在urllib中添加身份验证参数比请求模块更复杂

下面是一个使用请求模块的简洁解决方案:

import cv2
import requests
import numpy as np

r = requests.get('http://192.168.1.xx/mjpeg.cgi', auth=('user', 'password'), stream=True)
if(r.status_code == 200):
    bytes = bytes()
    for chunk in r.iter_content(chunk_size=1024):
        bytes += chunk
        a = bytes.find(b'\xff\xd8')
        b = bytes.find(b'\xff\xd9')
        if a != -1 and b != -1:
            jpg = bytes[a:b+2]
            bytes = bytes[b+2:]
            i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
            cv2.imshow('i', i)
            if cv2.waitKey(1) == 27:
                exit(0)
else:
    print("Received unexpected status code {}".format(r.status_code))
我也有同样的问题。 没有请求或urllib的解决方案:只需使用VideoCapture在cam地址中添加用户和密码,如下所示:

例如

cv2.视频捕获(“”)


使用android版IPWebcam。

我认为第一款anwser不适合其他格式的图像数据,例如png。 因此,我编写了以下代码,可以处理其他类型的图像

“”“
MJPEG格式
内容类型:multipart/x-mixed-replace;boundary=--BoundaryString
--边界字符串
内容类型:image/jpg
内容长度:12390
…图像数据在此。。。
--边界字符串
内容类型:image/jpg
内容长度:12390
…图像数据在此。。。
"""
输入io
导入请求
进口cv2
将numpy作为np导入
类MjpegReader():
定义初始化(self,url:str):
self.\u url=url
定义iter_内容(自身):
"""
提出:
访问违例
"""
r=requests.get(self.\u url,stream=True)
#解析边界
content\u type=r.headers['content-type']
index=content\u type.rfind(“boundary=”)
断言索引!=1
边界=内容\u类型[索引+长度(“边界=):]+“\r\n”
边界=边界。编码('utf-8')
rd=io.BufferedReader(r.raw)
尽管如此:
自我。跳到边界(rd,边界)
长度=自身长度(rd)
收益率rd.read(长度)
定义解析长度(self,rd)->int:
长度=0
尽管如此:
line=rd.readline()
如果行==b'\r\n':
返回长度
如果行开始使用(b“内容长度”):
长度=int(行解码('utf-8')。拆分(“:”[1])
断言长度>0
定义跳过边界(self、rd、boundary:字节):
对于范围(10)内的uu:
如果rd.readline()中有边界:
打破
其他:
引发运行时错误(“未检测到边界:”,边界)
mr=MjpegReader(“http://127.0.0.1/mjpeg.cgi")
对于mr.iter_content()中的内容:
i=cv2.imdecode(np.frombuffer(content,dtype=np.uint8),cv2.IMREAD\u COLOR)
cv2.imshow('i',i)
如果cv2.waitKey(1)==27:
打破

是CGI脚本返回视频流还是浏览器显示的HTML页面?@Andris它返回视频流,我尝试使用VLC播放它,效果很好。我没有IP摄像头,但在2009年与Axis摄像头进行了多次斗争。除此之外,可能会有所帮助。我看到你也返回了视频流,并且已经修复了mjpg。:)最后一个猜测是在OpenCV和IP摄像头之间使用gstreamer。@Andris我看到了,请看我对答案的评论。字节是一个不断增长的队列,它慢慢地被解析循环流消耗。read(16384)从http流中读取16384字节的数据,并将其添加到字节中,如果找到有效的jpeg帧,字节将被缩短。读缓冲区应该小于最小JPEG帧大小,否则可能会有问题。BTW,我也需要在C++中做同样的事情,这是在这里发布的。想法是一样的,但那里的实现比python更健壮,并且经过生产测试。如果您想为两个codebasehmm保持相同的行为,这可能对您很有用……我也很好奇如何做到这一点。我已经编辑了答案。我知道你在另一个问题中解决了这个问题,但我认为这个方法更好,因为gui会在这个答案中挂起io错误等。天哪!你是电脑黑客!有没有可能把它移植到Python3上?
import cv2
import urllib.request
import numpy as np

stream = urllib.request.urlopen('http://localhost:8080/frame.mjpg')
bytes = bytes()
while True:
    bytes += stream.read(1024)
    a = bytes.find(b'\xff\xd8')
    b = bytes.find(b'\xff\xd9')
    if a != -1 and b != -1:
        jpg = bytes[a:b+2]
        bytes = bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)
import cv2
import requests
import numpy as np

r = requests.get('http://192.168.1.xx/mjpeg.cgi', auth=('user', 'password'), stream=True)
if(r.status_code == 200):
    bytes = bytes()
    for chunk in r.iter_content(chunk_size=1024):
        bytes += chunk
        a = bytes.find(b'\xff\xd8')
        b = bytes.find(b'\xff\xd9')
        if a != -1 and b != -1:
            jpg = bytes[a:b+2]
            bytes = bytes[b+2:]
            i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
            cv2.imshow('i', i)
            if cv2.waitKey(1) == 27:
                exit(0)
else:
    print("Received unexpected status code {}".format(r.status_code))