下面给出的是用于从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),URL都不会被opencv打开。
通过http的Mjpeg是具有边界帧信息的multipart / x-mixed- replace,而jpeg数据只是以二进制形式发送。因此,您实际上不需要关心HTTP协议标头。所有jpeg帧均以marker开头,以0xff 0xd8结尾0xff 0xd9。因此,以上代码从http流中提取了此类帧,并对其进行了逐一解码。像下面一样。
0xff 0xd8
0xff 0xd9
...(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)
关于保存文件的问题,可以,只需很小的修改就可以使用相同的方法直接保存并重新打开文件。例如,您会做的curl http://IPCAM > output.mjpg ,然后更改行,stream=urllib.urlopen('http://localhost:8080/frame.mjpg')以便代码变为
curl http://IPCAM > output.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标头帧,例如通道,时间戳等,则保留它们可能会很有用。
import cv2 import urllib import numpy as np import Tkinter from PIL import Image, ImageTk import threading root = Tkinter.Tk() image_label = Tkinter.Label(root) image_label.pack() def cvloop(): 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) tki = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(i, cv2.COLOR_BGR2RGB))) image_label.configure(image=tki) image_label._backbuffer_ = tki #avoid flicker caused by premature gc cv2.imshow('i', i) if cv2.waitKey(1) == 27: exit(0) thread = threading.Thread(target=cvloop) thread.start() root.mainloop()