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

Sending image as numpy array over MQTT to AWS IoT Core

我正在使用 AWS IoT 设备 Python SDK 从网络摄像头捕获图像并将这些图像作为 numpy 数组发送到 AWS IoT Core。在 AWS IoT Core,这个 numpy 数组被传输到 lamda 函数进行图像处理(通过 RESNET 模型)。

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

所以我的问题是:

  1. 有没有办法增加 SDK 中的 MQTT TX 缓冲区大小?我没找到。
  2. 如果不是,那么通过 MQTT 发送和接收大型 numpy 数组的最佳方法是什么?

发布代码:

    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)

帧 numpy 数组:

[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 是二进制文件,因此您不能将其作为 JSON 发送,除非您先对其进行 base64 编码。在我下面的示例中,我展示了一种获取图像(Numpy 数组)和:

的方法
  • 将其转换为 JPEG。请注意,您同样可以使用 PNG - 特别是如果您想要无损 - 但通常会更慢。请注意,您同样可以使用 PIL/Pillow 而不是 OpenCV。请注意,您也可以改变质量,这会影响尺寸。
  • base64 编码
  • 转换为JSON

那我展示接收端的逆过程。实际 size/bandwith 节省将取决于您的图像及其可压缩程度以及您准备接受的质量损失,但是我从 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 编码:

# 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,编码,解码,带宽,最小化,最小化,减少,质数。