Python 3.x 通过MQTT将图像作为numpy阵列发送到AWS IoT核心

Python 3.x 通过MQTT将图像作为numpy阵列发送到AWS IoT核心,python-3.x,amazon-web-services,image-processing,mqtt,aws-iot,Python 3.x,Amazon Web Services,Image Processing,Mqtt,Aws Iot,我正在从网络摄像头捕获图像,并使用AWS物联网设备Python SDK将这些图像作为numpy阵列发送到AWS物联网核心。在AWS物联网核心,该numpy阵列被传输至lamda功能,用于图像处理(通过RESNET模型) 但numpy阵列的大小太大,无法通过MQTT发送,这就是为什么AWS IoT Core不接收它的原因 所以我的问题是: 有没有办法增加SDK中的MQTT TX缓冲区大小?我找不到 如果没有,那么通过MQTT发送并接收大numpy阵列的最佳方式是什么 发布代码: cam =

我正在从网络摄像头捕获图像,并使用AWS物联网设备Python SDK将这些图像作为numpy阵列发送到AWS物联网核心。在AWS物联网核心,该numpy阵列被传输至lamda功能,用于图像处理(通过RESNET模型)

但numpy阵列的大小太大,无法通过MQTT发送,这就是为什么AWS IoT Core不接收它的原因

所以我的问题是:

  • 有没有办法增加SDK中的MQTT TX缓冲区大小?我找不到
  • 如果没有,那么通过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方面的事情,但可以告诉你成像方面。我建议您将图像
    (是一个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编码之前执行此操作:

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

    阵列有多大?MQTT的最大有效负载大小为256mb,AWS可能有较小的限制。我已经添加了质疑中的数组信息。是的,但是在转换为JSON后,它有多大?我们已经是5mb的纯原始字节,将其转换为JSON表示可以轻松增加一个或多个数量级。您还可以利用JPEG压缩并发送JPEG图像并将其重新膨胀到接收端的Numpy阵列吗?这可能是该尺寸的十分之一,或更小。或者你能用一半大小的YUV吗?非常感谢!我真的被这个问题困住了。您的解决方案非常有效。很酷-很高兴它对您有效。祝你的项目好运!如果你再次陷入困境,请回来。问题和答案是免费的:-)