我想将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
Q:如何通过ZeroMQ从Raspberry Pi接收图像
PUB/SUB
在Python中?
首先,欢迎来到零禅艺术之地。
[如果一个人从未使用过ZeroMQ,在这里我们可能会喜欢先看一下[ZeroMQ Principles in less than Five Seconds],然后再探讨更多细节]
没有错误。
您应使用其他数据获取策略,并设置一些自卫参数。
[.recv_string()
-方法在阻止模式下被调用(它确实并且将永远阻止代码执行,直到任何可能的情况都满足规则才能交付为止)>
使用zmq.NOBLOCK
标志允许您避免这种阻塞模式+使用.poll()
方法可以帮助您设计私有事件驱动的循环的逻辑,以防万一.recv( zmq.NOBLOCK )
确实存在,得到交付。
[SUB
.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团队的开创性工作的几点评论,请阅读this和this。