首页 > 解决方案 > 通过 MQTT 将图像作为 numpy 数组发送到 AWS IoT Core

问题描述

我正在从网络摄像头捕获图像,并使用 AWS IoT Device 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

标签: python-3.xamazon-web-servicesimage-processingmqttaws-iot

解决方案


你似乎有点卡住了。我不了解 AWS 方面,但可以向您展示成像方面。我建议您将图像frame(这是一个 Numpy 数组)转换为 JPEG 图像进行传输,因为这将占用更少的带宽并导致更小的 MQTT 消息。但是,JPEG 是二进制的,因此您不能将其作为 JSON 发送,除非您先对其进行 base64 编码。在下面的示例中,我展示了一种获取图像(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 编码之前执行此操作:

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


推荐阅读