Загрузка потока MJPEG по кадре

106
12

У меня установлена IP-камера, и я могу перейти к ее IP-адресу и получить поток MJPEG, я пытаюсь загрузить его по кадру, чтобы я мог анализировать изображения на другом сервере. Однако у меня проблемы с чтением потока. Мой код:

import cv2
import urllib.request
import numpy as np
import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
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)

Это дает мне следующую ошибку:

Traceback (most recent call last):
File "mjpeg.py", line 15, in <module>
bytes += stream.read(1024)
TypeError: can only concatenate str (not "bytes") to str

Я думаю, что поток выводит строки, но как мне перейти на преобразование потока в байты и сохранение файла?

С уважением,

Ellens

спросил(а) 2018-12-07T15:51:00+03:00 1 год, 9 месяцев назад
1
Решение
57

concatenation работает только на том же типе ценности, что и

string with a string str += str
bytes with a bytes bytes += bytes

поэтому установите свою bytes переменную как bytes = b''. Надеюсь, что все будет хорошо. import cv2 import urllib.request import numpy as np import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = b''# MAKE IT 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)

ответил(а) 2018-12-07T15:58:00+03:00 1 год, 9 месяцев назад
40

Вам понадобятся bytes y, поэтому инициализировать bytes (которые, btw, не являются лучшими именами, как имя встроенного типа) в качестве байтовой строки, и использовать байтовые литералы для поиска маркеров начала и конца:


bytes = b''
while True:
bytes += stream.read(1024)
a = bytes.find(b'\xff\xd8')
b = bytes.find(b'\xff\xd9')
if a != -1 and b != -1:
# ...

ответил(а) 2018-12-07T15:56:00+03:00 1 год, 9 месяцев назад
41

Ваша байтовая переменная является str при инициализации (bytes = '') и not (bytes = b ''), измените это

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = ''
while True:

к этому

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = b''
while True:

вы можете сами убедиться в этом

>>> type('') == type(b'')
False
>>> type(''),type(b'')
(<class 'str'>, <class 'bytes'>)

ответил(а) 2018-12-07T15:56:00+03:00 1 год, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема