如何在Python中通过ZeroMQ PUB / SUB从Raspberry Pi接收图像?

问题描述 投票:1回答:1

我想将Picamera在Raspberry Pi上拍摄的图像发送到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

python sockets raspberry-pi pyzmq picamera
1个回答
0
投票

Q如何通过ZeroMQ从Raspberry Pi接收图像PUB/SUB在Python中?

首先,欢迎来到零禅艺术之地。


[如果一个人从未使用过ZeroMQ,在这里我们可能会喜欢先看一下[ZeroMQ Principles in less than Five Seconds],然后再探讨更多细节]


观察:

没有错误。

您应使用其他数据获取策略,并设置一些自卫参数。

[.recv_string()-方法在阻止模式下被调用(它确实并且将永远阻止代码执行,直到任何可能的情况都满足规则才能交付为止)>

使用zmq.NOBLOCK标志允许您避免这种阻塞模式+使用.poll()方法可以帮助您设计私有事件驱动的循环的逻辑,以防万一.recv( zmq.NOBLOCK )确实存在,得到交付。

[SUB

端将不接收任何消息,除非已正确订阅以接收某些内容,否则默认状态(如报纸一样)将不接收任何消息,除非已明确订阅-Asahi Shimbun或其他标题-。按照API记录的策略,订阅任何内容的最安全方式是使用.setsockopt( zmq.SUBSCRIBE, "" )方法订阅长度为零的字符串。

最后但并非最不重要的一点是,如果愿意进行RPi-Win流式传输,可能会有一个老虎钳策略,因为除了最近的frame之外,其他任何队列都无法入队/发布/传输/接收/出队通常没有任何价值。 ,其已准备好.setsockopt( zmq.CONFLATE, 1 )

[您可能需要更多的资源调整,以提高.Context( nIOthreads )实例的性能,保留的队列深度,L3堆栈参数以及许多其他可能的增强。

总是设置.setsockopt( zmq.LINGER, 0 )

,因为您永远不知道将连接哪个版本以及可能发生的默认设置,这里有机会让您崩溃的套接字实例永久挂起(通常在操作系统重新启动之前) ),对于任何生产级软件而言,这似乎都是一个难以处理的风险因素,不是吗?

解决方案技巧:
  • 要避免错过unicode约定的风险,这些约定在Linux端发起方和Windows O / S端之间互不相同。

[+

由于unicode对象具有广泛的表示形式,根据它们的编码,它们作为字节<>,而是采用称为UCS的格式(较早的固定宽度Unicode格式)。在某些平台(OS X,Windows)上,存储为UCS-2,每个字符2个字节。在大多数与平台有关的。...+这里的效率问题来自这样一个事实,即简单的ascii字符串在内存中的大小是所需大小的4倍(在大多数Linux上是2x,在其他平台上)。另外,要与使用char的C代码进行互译,必须始终复制数据并对字节进行编码/解码。从内存的角度来看,这确实是非常低效的。本质上,在内存效率对您很重要的地方,永远不要使用字符串。使用字节。问题在于用户几乎总是使用str,而在2.x中它们是有效的,而在3.x中则不是。我们希望确保我们不会帮助用户犯此错误,因此我们确保zmq方法不会尝试隐藏真正的字符串。了解有关ZeroMQ中避免延迟的更多信息,如果尝试流式传输常量图像和先验已知图像( 640 x 480 x <colordepth> ),则转换成本很高,将小尺寸,低分辨率,低FPS RGB / IR图片转换为JPEG如果在RPi和Win-device之间使用本地LAN或专用WLAN段,则仅用于传输的-file格式是没有意义的。延迟驱动的设计可以通过使用cPickle.dumps()dill.dumps()进行测试,并可能避免任何形式的数据压缩,而是在二进制块BLOB中发送尽可能紧凑的数据,通常足以使用aNumpyObject.data实用程序进行发送直接从<read-write buffer for 0x7fa3cbe3f8a0, size 307200, offset 0 at 0x7f632bb2cc30>开始或使用struct.pack() / .unpack()方法进行一些二进制处理,如果需要超越numpy可用的.data访问技巧。所有给定的.setsockopt( zmq.CONFLATE, 1 )都在两侧被激活,以避免过多深度缓冲实时流数据。
  • 出于性能和延迟原因,您可以避免使用PUB/SUB对原型,因为ZeroMQ API v3。+已将TOPIC过滤的工作负载移至了PUB端,这是您较弱的一环节点(虽然RPi具有多个核心,并且您可以提高类固醇的.Context( nIOthreads )实例,以具有更大的I / O功率,但是与Windows端的本地主机相比,RPi具有GHz的一部分,并且具有机械手紧凑性)控制循环可能已经耗尽了大部分控制权)。对于[一对一]拓扑,使用PUSH/PULL非常适合,并且由于避免了RPi方面的处理,因此具有较少的处理和E2E延迟开销。

  • 对于基于.poll()的,具有不同优先级的事件处理程序,以及关于Margaret HAMILTON夫人及其MIT团队的开创性工作的几点评论,请阅读thisthis
  • © www.soinside.com 2019 - 2024. All rights reserved.