My goal is to send images and data string from a RPi (server) to a client. I use send_json(data)
where the data is a dict {'img': img_ls, 'telemetry':'0.01, 320, -10'}
. img_ls
is the image converted to a list. The problem is that I get len( img_ls ) = 57556
, whereas the original image has a size: 320 x 240 = 76800. I don't understand why the discrepancy. Here is the code:
SERVER-side
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://0.0.0.0:5557")
def outputs():
stream = io.BytesIO()
while True:
yield stream
stream.seek(0)
sensors = '0.01, 320, -10'
img_ls = np.fromstring(stream.getvalue(), dtype=np.uint8).tolist()
data = {'telemetry': sensors, 'img': img_ls}
socket.send_json(data)
stream.seek(0)
stream.truncate()
with picamera.PiCamera() as camera:
camera.resolution = (320, 240)
camera.framerate = 80
time.sleep(2)
camera.capture_sequence(outputs(), 'jpeg', use_video_port=True)
CLIENT-side
ip_server = "192.168.42.1"
context = zmq.Context()
zmq_socket = context.socket(zmq.SUB)
zmq_socket.setsockopt(zmq.SUBSCRIBE, b'')
zmq_socket.setsockopt(zmq.CONFLATE, 1)
zmq_socket.connect("tcp://{}:5557".format(ip_server))
try:
img_nbr = 1
while True:
start = time.time()
frames = zmq_socket.recv_json()
img_ls = frames['img']
telemetry = frames['telemetry']
#convert img list to array
img_arr = np.asarray(img_ls)
#reshape gives error because 320*240 != len(img_ls)
image = np.reshape(img_ls, (320, 240))
#save image file locally
image = Image.fromarray(image)
#timestamp in ms
timestamp = int(time.time() * 1000 )
image.save('img_'+str(timestamp)+'.jpg')
print('Frame number: ', str(img_nbr))
img_nbr += 1
finally:
pass
Final note: this is my attempt to stream images and sensors data synchronously from RPi to client. I am afraid that the array and list conversion ( done on the RPi side ) might slow down the streaming. If there is a better way to do that with ( still ) using zmq
, please let me know.
struct_pack
(struct_unpack
) and it goes in the code. I modified the initial code for the "server-side" to generate np array - Replacedstream = io.BytesIO()
bystream = PiRGBArray(camera, size=resolution)
;def output()
bydef outputs(camera, resolution)
; andcamera.capture_sequence(outputs(), 'jpeg', use_video_port=True) by camera.capture_sequence(outputs(camera, resolution), 'rgb', use_video_port=True). BTW, I use 'capture_sequence" rather than (single shot)
capture` because of higher fps. – Whereat