Im Folgenden finden Sie den Code zum Abrufen von Live-Streams von einer IP-Kamera.
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
Beim Ausführen des Codes erhalte ich folgende Ausgabe:
Cam not found
Wo gehe ich falsch? Auch, warum ist Frame None hier? Gibt es ein Problem mit der Konvertierung?
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)
Ich habe gerade gesehen, dass Sie erwähnen, dass Sie C++ - Code haben, der funktioniert, wenn dies der Fall ist, funktioniert Ihre Kamera möglicherweise auch in python. Der obige Code analysiert den mjpeg-Stream manuell, ohne sich auf opencv zu verlassen , da in einigen meiner projekte die url von opencv nicht geöffnet wird, egal was ich gemacht habe (c ++, python).
Mjpeg über http ist multipart/x-mixed-replace mit Boundary Frame Info und JPEG-Daten werden nur binär gesendet. Sie müssen sich also nicht wirklich um HTTP-Protokollheader kümmern. Alle JPEG-Frames beginnen mit dem Marker 0xff 0xd8
Und enden mit 0xff 0xd9
. Der obige Code extrahiert solche Frames aus dem http-Stream und decodiert sie nacheinander. Wie unten.
...(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)
In Bezug auf Ihre Frage zum Speichern der Datei kann die Datei mit der gleichen Methode mit sehr geringen Änderungen direkt gespeichert und wieder geöffnet werden. Zum Beispiel würden Sie curl http://IPCAM > output.mjpg
Ausführen und dann die Zeile stream=urllib.urlopen('http://localhost:8080/frame.mjpg')
so ändern, dass der Code zu diesem Code wird
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)
Natürlich speichern Sie eine Menge redundanter HTTP-Header, die Sie möglicherweise entfernen möchten. Oder wenn Sie zusätzliche CPU-Leistung haben, verschlüsseln Sie sie einfach zuerst nach h264. Wenn die Kamera jedoch einige Metadaten zu HTTP-Header-Frames wie Kanal, Zeitstempel usw. hinzufügt, kann es hilfreich sein, diese beizubehalten.
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()
Beachten Sie bitte zunächst, dass Sie zuerst versuchen einfach die Videoaufnahmefunktionen von OpenCV verwenden sollten direkt, z. cv2.VideoCapture('http://localhost:8080/frame.mjpg')
!
Das funktioniert gut für mich:
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)
Wie auch immer, hier ist die Lösung von Zaw Lin, die auf OpenCV 3 portiert wurde (nur die Änderung ist cv2.CV_LOAD_IMAGE_COLOR
bis cv2.IMREAD_COLOR
und Python 3 (String vs. Byte-Behandlung geändert plus urllib):
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)
Hier ist eine Antwort mit dem Python 3 Anfragen -Modul anstelle von rllib.
Der Grund für die Nichtverwendung von urllib ist, dass eine URL wie http://user:[email protected]:port
Nicht korrekt interpretiert werden kann.
Das Hinzufügen von Authentifizierungsparametern ist in urllib komplexer als im Anforderungsmodul.
Hier ist eine nette, prägnante Lösung mit dem Anforderungsmodul:
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))