2017-08-28 17 views
1

ラズベリーパイ(Raspivid/H.264)からネットワーク経由でラップトップ上で実行されるOpenCVアプリケーションにビデオをストリーミングするのが目的です。 (C++)は次のようNetcat H.264ビデオをRaspividからOpenCVに

オープンCVキャプチャは次のとおりです。

cv::VideoCapture cap; 
cap.open("cam_1"); // cam_1 is a FIFO 

cv::Mat frame; 

while(1){ 
    cap >> frame; 
    cv::imshow("", frame); 
    cv::waitKey(10); 
} 

次のようにFIFOストリームが作成されます。

mkfifo cam_1 

OpenCVのプログラムが実行されると、netcatをリスナーが開始されます。

ncat --recv-only --keep-open --verbose --listen 5001 > cam_1 

ラップトップでnetcatリスナーが実行されると、ストリームはth Eラズベリーパイ

raspivid --verbose --nopreview -b 2000000 --timeout 0 -o - | ncat 192.168.LAPTOP.IP 5001 

又は、デバッグのために、ラップトップ上のローカルファイルのnetcatにストリーミングすることができる。

Unable to stop the stream: Inappropriate ioctl for device (ERROR)icvOpenAVI_XINE(): Unable to initialize video driver.

次のエラーを与える

cat video.h264 | nc 192.168.LAPTOP.IP 5001 

どちらも興味深いのは、ラップトップでNetcatリスナーを起動し、CTRL + Cでビデオストリームを終了し、ビデオストリームを開始する前にもう一度起動すると、どちらの方法でも... ビデオp適切に寝る。

なぜnetcatリスナーを起動してからそれを終了させたのか分かりませんが、再び起動すると影響が出ます。私はおそらく、ビデオの前にFIFOにEOFまたはBOFをエコーする必要があると考えました。その構文が何であるかはわかりません。

私はNetcatを、すべての味を試してみました。

+0

https://stackoverflow.com/a/44972255/2836621でPythonスクリプトを実行してください。 –

答えて

1

OpenCVがそれを読み込もうとした後で、それにストリーミングを開始する前にFIFOをタッチすると、それが機能します。

1

私はちょうど私がラズベリーパイでこのpicamera python recipe

を適応させることになったhttps://stackoverflow.com/a/48675107/2355051

次を使用して、これを解く:(createStream.py)処理されているマシンで

import io 
import socket 
import struct 
import time 
import picamera 

# Connect a client socket to my_server:8000 (change my_server to the 
# hostname of your server) 
client_socket = socket.socket() 
client_socket.connect(('10.0.0.3', 777)) 

# Make a file-like object out of the connection 
connection = client_socket.makefile('wb') 
try: 
    with picamera.PiCamera() as camera: 
     camera.resolution = (1024, 768) 
     # Start a preview and let the camera warm up for 2 seconds 
     camera.start_preview() 
     time.sleep(2) 

     # Note the start time and construct a stream to hold image data 
     # temporarily (we could write it directly to connection but in this 
     # case we want to find out the size of each capture first to keep 
     # our protocol simple) 
     start = time.time() 
     stream = io.BytesIO() 
     for foo in camera.capture_continuous(stream, 'jpeg', use_video_port=True): 
      # Write the length of the capture to the stream and flush to 
      # ensure it actually gets sent 
      connection.write(struct.pack('<L', stream.tell())) 
      connection.flush() 

      # Rewind the stream and send the image data over the wire 
      stream.seek(0) 
      connection.write(stream.read()) 

      # Reset the stream for the next capture 
      stream.seek(0) 
      stream.truncate() 
    # Write a length of zero to the stream to signal we're done 
    connection.write(struct.pack('<L', 0)) 
finally: 
    connection.close() 
    client_socket.close() 

ストリーム:(processStream.py)

import io 
import socket 
import struct 
import cv2 
import numpy as np 

# Start a socket listening for connections on 0.0.0.0:8000 (0.0.0.0 means 
# all interfaces) 
server_socket = socket.socket() 
server_socket.bind(('0.0.0.0', 777)) 
server_socket.listen(0) 

# Accept a single connection and make a file-like object out of it 
connection = server_socket.accept()[0].makefile('rb') 
try: 
    while True: 
     # Read the length of the image as a 32-bit unsigned int. If the 
     # length is zero, quit the loop 
     image_len = struct.unpack('<L', connection.read(struct.calcsize('<L')))[0] 
     if not image_len: 
      break 
     # Construct a stream to hold the image data and read the image 
     # data from the connection 
     image_stream = io.BytesIO() 
     image_stream.write(connection.read(image_len)) 
     # Rewind the stream, open it as an image with opencv and do some 
     # processing on it 
     image_stream.seek(0) 
     image = Image.open(image_stream) 

     data = np.fromstring(image_stream.getvalue(), dtype=np.uint8) 
     imagedisp = cv2.imdecode(data, 1) 

     cv2.imshow("Frame",imagedisp) 
     cv2.waitKey(1) #imshow will not output an image if you do not use waitKey 
     cv2.destroyAllWindows() #cleanup windows 
finally: 
    connection.close() 
    server_socket.close() 

この解決策は私の元の質問で参照したビデオと同様の結果をもたらします。解像度フレームを大きくすると、フィードのレイテンシが増えますが、これはアプリケーションの目的には許容できます。

まずprocessStream.pyを実行し、次にRaspberry PiでcreateStream.pyを実行する必要があります。これが動作しない場合は、sudo

関連する問題