Ответ 1
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)
изменить (объяснение)
Я только что увидел, что вы упоминаете, что у вас есть код С++, который работает, если это так, ваша камера может работать и на python. Приведенный выше код вручную анализирует поток mjpeg, не полагаясь на opencv, так как в некоторых моих проектах url не будет открыт opencv независимо от того, что я сделал (С++, python).
Mjpeg через http является 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)
edit 2 (чтение из файла 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, которые вы можете удалить. Или, если у вас есть дополнительная мощность процессора, возможно, просто сначала закодируйте h264. Но если камера добавляет некоторые метаданные в кадры заголовка http, такие как канал, временная метка и т.д. Тогда может быть полезно сохранить их.
edit 3 (интерфейс 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()