cam python opencv live-streaming ip-camera mjpeg

python - cam - ¿Cómo analizar mjpeg http stream desde la cámara ip?



python webcam streaming (4)

A continuación se muestra el código escrito para obtener transmisión en vivo desde una cámara 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

Al ejecutar el código, el resultado que obtengo es:

Cam not found

¿A dónde me voy mal? Además, ¿por qué está el cuadro Ninguno aquí? ¿Hay algún problema con la conversión?


Aquí hay una respuesta utilizando el módulo de solicitudes de Python 3 en lugar de urllib .

La razón para no usar urllib es que no puede interpretar correctamente una URL como http://user:pass@ipaddress:port

Agregar parámetros de autenticación es más complejo en urllib que el módulo de solicitudes.

Aquí hay una solución agradable y concisa usando el módulo de solicitudes:

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))


En primer lugar, tenga en cuenta que primero debe intentar usar las funciones de captura de video de OpenCV directamente , por ejemplo, cv2.VideoCapture(''http://localhost:8080/frame.mjpg'') .

Esto funciona bien para mí:

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)

De todos modos, aquí está la solución de Zaw Lin portada a OpenCV 3 (solo el cambio es cv2.CV_LOAD_IMAGE_COLOR a cv2.IMREAD_COLOR y Python 3 (el manejo de la cadena frente a los bytes cambió más 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)


Yo tuve el mismo problema. La solución sin solicitudes o urllib: simplemente agregue el usuario y la contraseña en la dirección de la cámara, usando VideoCapture, como esto:

P.ej

cv2.VideoCapture ('' http: // usuario: [email protected]/video '')

utilizando IPWebcam para Android.


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)

editar (explicación)

Acabo de ver que mencionas que tienes un código c ++ que está funcionando, si ese es el caso, tu cámara también podría funcionar en python. El código anterior analiza manualmente el flujo de mjpeg sin depender de opencv, ya que en algunos de mis proyectos, la url no se abrirá con opencv, no importa lo que hice (c ++, python).

Mjpeg sobre http es multipart / x-mixed-replace con información de marco de límite y los datos jpeg se envían en formato binario. Por lo tanto, no es necesario preocuparse por los encabezados de protocolo http. Todas las tramas jpeg comienzan con el marcador 0xff 0xd8 y terminan con 0xff 0xd9 . Por lo tanto, el código anterior extrae dichos marcos de la secuencia http y los decodifica uno por uno. como abajo.

...(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)

edición 2 (lectura de archivo mjpg)

Con respecto a su pregunta de guardar el archivo, sí, el archivo se puede guardar y reabrir directamente usando el mismo método con una modificación muy pequeña. Por ejemplo, haría curl http://IPCAM > output.mjpg y luego cambiaría el stream=urllib.urlopen(''http://localhost:8080/frame.mjpg'') línea stream=urllib.urlopen(''http://localhost:8080/frame.mjpg'') para que el código se convierta en este

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)

Por supuesto, está guardando muchos encabezados http redundantes, que tal vez quiera quitar. O si tiene potencia de CPU adicional, tal vez simplemente codifique a h264 primero. Pero si la cámara está agregando algunos metadatos a los marcos del encabezado http, como el canal, la marca de tiempo, etc. Entonces puede ser útil mantenerlos.

edición 3 (interfaz tkinter)

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()