通过MQTT将图像作为numpy数组发送到AWS IoT Core



我正在从网络摄像头捕获图像,并使用AWS IoT Device Python SDK将这些图像作为numpy数组发送到AWS IoT Core。在AWS物联网核心,这个numpy数组被转移到lambda函数进行图像处理(通过RESNET模型)。

但是numpy数组的大小太大,无法通过MQTT发送,这就是AWS IoT Core无法接收它的原因。

我的问题是:

  1. 是否有一种方法来增加MQTT TX缓冲区大小在SDK?我找不到。
  2. 如果不是,那么通过MQTT发送大numpy数组并接收它的最佳方法是什么?
  3. 发布代码:

cam = cv2.VideoCapture(0)
ret, frame = cam.read()
message['image'] = frame.tolist() #numpy array converted to list to make it work with json.dumps
messageJson = json.dumps(message)
myAWSIoTMQTTClient.publish(topic, messageJson, 0)

Frame numpy array:

[0:480] :[array([[156, 168, 20...ype=uint8), array([[155, 167, 20...ype=uint8), array([[144, 168, 20...ype=uint8), array([[144, 168, 20...ype=uint8), array([[138, 168, 20...ype=uint8), array([[138, 168, 20...ype=uint8), array([[149, 170, 20...ype=uint8), array([[151, 172, 20...ype=uint8), array([[156, 174, 20...ype=uint8), array([[156, 174, 20...ype=uint8), array([[153, 174, 20...ype=uint8), array([[152, 173, 20...ype=uint8), array([[153, 172, 20...ype=uint8), array([[154, 173, 20...ype=uint8), ...]
dtype:dtype('uint8')
max:222
min:0
shape:(480, 640, 3)
size:921600

你好像有点卡住了。我不太了解AWS,但我可以告诉你成像方面的情况。我建议您将图像frame(这是一个Numpy数组)转换为JPEG图像进行传输,因为这将占用更少的带宽并产生更小的MQTT消息。但是,JPEG是二进制的,所以除非先对其进行base64编码,否则不能将其作为JSON发送。在下面的例子中,我展示了一种获取图像(Numpy数组)的方法:

  • 转换为JPEG。请注意,您同样可以使用PNG -特别是如果您想要无损-但通常会较慢。注意,您也可以同样使用PIL/Pillow而不是OpenCV. 注意,你也可以改变质量,这会影响大小。
  • base64编码它
  • 转换成JSON

则显示接收端的反向过程。实际的大小/带宽节省将取决于您的图像以及它的可压缩性以及您准备接受的质量损失,但是我从920kB的图像开始,实际上用66kB的JSON表示它。

#!/usr/bin/env python3
import cv2
import numpy as np
from base64 import b64encode
# Get any old image, 640x480 pixels - corresponds to your "frame"
na = cv2.imread('start.jpg', cv2.IMREAD_COLOR)
print(f'DEBUG: Size as Numpy array: {na.nbytes}')
# Convert to "in-memory" JPEG
_, JPEG = cv2.imencode(".jpg", na, [int(cv2.IMWRITE_JPEG_QUALITY), 80])
print(f'DEBUG: Size as JPEG: {JPEG.nbytes}')
JPEG.tofile('DEBUG-original.jpg')
# Base64 encode
b64 = b64encode(JPEG)
print(f'DEBUG: Size as base64: {len(b64)}')
print(f'DEBUG: Start of base64: {b64[:32]}...')
# JSON-encode
message = { "image": b64.decode("utf-8") }
messageJSON = json.dumps(message)
print(f'DEBUG: Start of JSON: {messageJSON[:32]}')

DEBUG: Size as Numpy array: 921600
DEBUG: Size as JPEG: 49456
DEBUG: Size as base64: 65944
DEBUG: Start of base64: b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD'...
DEBUG: Start of JSON: {"image": "/9j/4AAQSkZJRgABAQAAA

接收端看起来像这样:

### RECEIVER: All variables suffixed with '_r' to denote receiver ###
import cv2
import numpy as np
from base64 import b64decode
# Extract base64 from JSON
b64_r = json.loads(messageJSON)
# Extract JPEG-encoded image from base64-encoded string
JPEG_r = b64decode(b64_r["image"])
# Decode JPEG back into Numpy array
na_r = cv2.imdecode(np.frombuffer(JPEG_r,dtype=np.uint8), cv2.IMREAD_COLOR)

注意:如果你想转换为灰度,你需要在之前做JPEG-encoding:

# Convert to greyscale
grey = cv2.cvtColor(na, cv2. COLOR_BGR2GRAY)
# JPEG-encode
_, JPEG = cv2.imencode(".jpg", grey, [int(cv2.IMWRITE_JPEG_QUALITY), 80])
关键字

: Python、MQTT、AWS、图像处理、JSON、base64、编码、解码、带宽、最小化、最小化、减少、质数

最新更新