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)
_
カメラがpythonで動作する場合もあります。上記のコードはopencvに依存せずにmjpegストリームを手動で解析します。なぜなら、私のプロジェクトのいくつかでは、私が何をしたとしても、opencvによってURLが開かれないからです(c ++、python)。
Http上のMjpegは、境界フレーム情報を含むmultipart/x-mixed-replaceであり、jpegデータはバイナリで送信されます。したがって、httpプロトコルヘッダーを実際に考慮する必要はありません。すべてのjpegフレームはマーカー_0xff 0xd8
_で始まり、_0xff 0xd9
_で終わります。したがって、上記のコードはhttpストリームからそのようなフレームを抽出し、それらを1つずつデコードします。以下のように。
_...(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')
soの行を変更して、コードが次のようになるようにします。
_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()
_
まず、最初の試行 OpenCVのビデオキャプチャ機能を使用するだけ直接にする必要があることに注意してください。 cv2.VideoCapture('http://localhost:8080/frame.mjpg')
!
これは私にとってはうまくいきます:
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)
とにかく、ここにOpenCV 3に移植されたZaw Linのソリューションがあります(変更点はcv2.CV_LOAD_IMAGE_COLOR
からcv2.IMREAD_COLOR
およびPython 3(文字列とバイトの処理の変更に加えて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)
rllibの代わりにPython 3 requestsモジュールを使用した回答です。
Urllibを使用しない理由は、http://user:pass@ipaddress:port
のようなURLを正しく解釈できないためです。
認証パラメータの追加は、urllibでは要求モジュールよりも複雑です。
以下は、requestsモジュールを使用したニースの簡潔なソリューションです。
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))