1

Raspberry Pi の Picamera で撮影した画像を Windows コンピューターに送信したいと考えています。

次のようにいくつかのコードを書きました (ここでは簡略化しています
frame = footage_socket.recv_string() ) client.py

エラーは発生しませんが、コードがフリーズして次の行に移動できないなど、常にコードにスタックします。正常に動作し、連続server.pyして印刷されます。'test'を見ると、jpg_as_textエンコードされたテキストが表示されます。

server.py:

import picamera
import socket
import threading
import zmq
import cv2
import base64
from picamera.array import PiRGBArray

if __name__ == "__main__":

    addr = 'ip_address'

    camera = picamera.PiCamera()                 # Camera initialization
    camera.resolution = (640, 480)
    camera.framerate = 7
    rawCapture = PiRGBArray(camera, size=(640, 480))

    # FPV initialization
    context = zmq.Context()
    footage_socket = context.socket(zmq.PUB)
    footage_socket.connect('tcp://%s:5555'%addr)
    print(addr)

    font = cv2.FONT_HERSHEY_SIMPLEX
    for frame in camera.capture_continuous( rawCapture,
                                            format         = "bgr",
                                            use_video_port = True ):
        image = frame.array
        print('test')
        image = cv2.resize(image, (640, 480))    # resize the frame
        encoded, buffer = cv2.imencode('.jpg', image)
        jpg_as_text = base64.b64encode(buffer)
        footage_socket.send(jpg_as_text)
        rawCapture.truncate(0)

client.py:

from socket import *
import sys
import time
import threading as thread
import tkinter as tk
import math
import os
import cv2
import zmq
import base64
import numpy as np


if __name__ == "__main__":

    context = zmq.Context()
    footage_socket = context.socket(zmq.SUB)
    footage_socket.bind('tcp://*:5555')
    footage_socket.setsockopt_string(zmq.SUBSCRIBE, np.unicode(''))

    font = cv2.FONT_HERSHEY_SIMPLEX

    while 100:
        try:
            frame = footage_socket.recv_string() # This line of code is the problem.

            print('next successfuly connected')
            img = base64.b64decode(frame)
            npimg = np.frombuffer(img, dtype=np.uint8)
            source = cv2.imdecode(npimg, 1)
            cv2.imshow("Stream", source)
            cv2.waitKey(1)

        except KeyboardInterrupt:
            break
        except:
            pass
    
4

1 に答える 1

0

Q : Pythonで ZeroMQPUB/SUBを介して Raspberry Pi から画像を受信するにはどうすればよいですか?

ZeroMQ を使用したことがない場合は、ここで「5 秒以内にわかる ZeroMQの原則」を最初に見てから、詳細に飛び込むことをお勧めします。

観察 :

バグはありません。

他のデータ取得戦略を使用し、いくつかの自己防衛パラメータを設定します。

.recv_string()-メソッドはブロッキングモードで呼び出されます(もっともらしいものがルールを満たして成果物になるまで、コードの実行を永久にブロックします)

flag を使用zmq.NOBLOCKすると、このようなブロッキング モードを回避できます + .poll()-method を使用すると、場合に備えて必要なプライベート イベント ドリブン ループのロジックを設計するのに役立ちます.recv( zmq.NOBLOCK )

SUB-サイドは、何かを受け取るために適切に購読しない限り、何も受け取りません。デフォルトの状態は、朝日新聞または他のタイトルに明示的に購読しない限り、新聞の場合と同様に、何も受け取りません。API で文書化された戦略に従って、コンテンツをサブスクライブする最も安全なモードは、.setsockopt( zmq.SUBSCRIBE, "" )-method を使用して長さ 0 の文字列をサブスクライブすることです。

最後に大事なことを言い忘れましたが、RPi-Win ストリーミングを実行したい場合は万力の戦略があるかもしれません。frameこれ.setsockopt( zmq.CONFLATE, 1 )は、準備ができている最新の . .

.Context( nIOthreads )-instance のパフォーマンス、予約されたキューの深さ、L3 スタックのパラメータ、およびその他の多くの拡張機能を向上させるために、リソースをさらに微調整する必要がある場合があります。

どのバージョンが接続されるか、どのデフォルトが行われるかがわからない場合は、常に設定.setsockopt( zmq.LINGER, 0 )してください。ここでは、クラッシュしたソケットのインスタンスが永久にハングする可能性があります (ほとんどの場合、O/S の再起動まで)。プロダクショングレードのソフトウェアのリスク要因ですね。


解決策のヒント:

  • Linux 側の発信元と Windows O/S 側の間で互いに一致しない異なる Unicode 規則を見逃しているリスクを回避します。

+
Unicode オブジェクトには幅広い表現があるため、エンコードに従ってバイトとして保存されるのではなく、UCS (古い固定幅 Unicode 形式) と呼ばれる形式で保存されます。一部のプラットフォーム (OS X、Windows) では、ストレージは UCS-2 で、1 文字あたり 2 バイトです。ほとんどのix システムでは、UCS-4、つまり 1 文字あたり 4 バイトです。Unicode オブジェクトのバッファの内容はエンコーディングに依存しませんが (常に UCS-2 または UCS-4)、プラットフォームに依存します。
...
+
ここでの効率の問題は、単純な ascii 文字列が必要なメモリの 4 倍 (ほとんどの Linux では、他のプラットフォームでは 2 倍) の大きさであるという事実から生じます。また、char で動作する C コードとの間で変換するには
、常にデータをコピーしてバイトをエンコード/デコードする必要があります。これは、メモリの観点から見ると、非常に非効率的です。基本的に、メモリ効率が重要な場合は、文字列を使用しないでください。バイトを使用します。問題は、ユーザーがほぼ常に を使用することですstr。2.x では効率的ですが、3.x ではそうではありません。ユーザーがこの間違いを犯すのを助けないようにしたいので、zmqメソッドが実際の文字列を隠そうとしないようにします。

  • ZeroMQ でのレイテンシー回避について詳しくは、一定のアプリオリな既知の画像をストリーミングしようとする場合( 640 x 480 x <colordepth> )- 変換に費用がかかり、転送のためだけに小規模で低解像度、低 FPS の RGB / IR 画像を JPEG ファイル形式に変換することは、 RPi と Win デバイスの間でローカル LAN または専用の WLAN セグメントが使用されている場合は意味がありません。レイテンシーを動機とする設計では、バイナリ ブロック BLOB を使用してデータを圧縮することをテストし、おそらく回避する可能性があります。ほとんどの場合、ユーティリティを使用して直接送信するcPickle.dumps()か、 /を使用してバイナリ マングリングを実行するのに十分です。 -メソッド、利用可能な-access トリックを超える必要がある場合。すべて与えられたdill.dumps()aNumpyObject.data<read-write buffer for 0x7fa3cbe3f8a0, size 307200, offset 0 at 0x7f632bb2cc30>struct.pack().unpack()numpy.data.setsockopt( zmq.CONFLATE, 1 )ライブ ストリーミング データのバッファリングの過度の深さを回避するために、両側でアクティブ化されました。

  • パフォーマンスとレイテンシの両方の理由から、PUB/SUBZeroMQ API v3.+ がトピック フィルタリングのワークロードをPUB弱いノードである -side に移動したため、アーキタイプのペアを避けることができます (RPi にはいくつかのコアがあり、 -instance をステロイドでブーストして.Context( nIOthreads )、I/O により多くの電力を供給しますが、RPi は Windows 側のローカルホストと比較して数分の 1 GHz しかありません。 )。使用PUSH/PULLは、1 対 1 トポロジーの場合とまったく同じように適合し、加えて、RPi 側での処理が回避されるため、処理と E2E レイテンシーのオーバーヘッドが少なくなります。

.poll()基づいた、異なる優先順位のイベント ハンドラー、およびマーガレット ハミルトン夫人と彼女の MIT チームの影響力のある仕事についてのいくつかの発言については、こちらこちらをお読みください。

于 2020-04-26T20:21:24.443 に答える