python - 以 JSON 格式发送 OpenCV 图像

标签 python json opencv base64 python-imaging-library

我正在尝试在 json 中发送 OpenCV 图像并在另一端接收它,但我遇到了无穷无尽的图像编码和解码问题

我通过以下方式以 JSON 格式发送它:

dumps({"image": b64encode(image[y1:y2, x1:x2]).decode('utf-8')})

在另一端,我尝试解码它(我需要它作为 Pillow 图像):

image = Image.open(BytesIO(base64.b64decode(data['image'])))

但我得到了 Exception cannot identify image file <_io.BytesIO object at 0x7fbd34c98a98>

还试过:

nparr = np.fromstring(b64decode(data['image']), np.uint8)
image = cv2.imdecode(nparr, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(image)

但后来我得到 'NoneType' object has no attribute '__array_interface__'来自 Image.fromarray

知道我做错了什么吗?

最佳答案

希望这能让您入门。我认为您尝试过的方法,即从 Numpy 数组发送未经修饰的字节可能行不通,因为接收方不知道图像中的宽度、高度和 channel 数,所以我使用了 pickle存储它。

#!/usr/bin/env python3

import cv2
import numpy as np
import base64
import json
import pickle
from PIL import Image

def im2json(im):
    """Convert a Numpy array to JSON string"""
    imdata = pickle.dumps(im)
    jstr = json.dumps({"image": base64.b64encode(imdata).decode('ascii')})
    return jstr

def json2im(jstr):
    """Convert a JSON string back to a Numpy array"""
    load = json.loads(jstr)
    imdata = base64.b64decode(load['image'])
    im = pickle.loads(imdata)
    return im

# Create solid red image 
red = np.full((480, 640, 3), [0, 0, 255], dtype=np.uint8)  

# Make image into JSON string
jstr = im2json(red)

# Extract image from JSON string, and convert from OpenCV to PIL reversing BGR to RGB on the way
OpenCVim = json2im(jstr)
PILimage = Image.fromarray(OpenCVim[...,::-1])
PILimage.show()

由于您没有在评论中回答我关于为什么您想以这种方式做事的问题,它可能不是最佳选择 - 通过网络发送未压缩的 base64 编码图像(大概)是效率不高。例如,您可能会考虑使用 JPEG 或 PNG 编码数据来节省网络带宽。

你也可以使用 cPickle相反。


请注意,有些人不赞成 pickle,而且上述方法会占用大量网络带宽。另一种方法可能是在发送之前用 JPEG 压缩图像,然后在接收端直接解压缩为 PIL 图像。请注意,这是有损

或者将代码中的 .JPG 扩展名更改为 .PNG 这是无损的,但可能会更慢并且不适用于具有 float 据或 16 的图像位数据(虽然后者可以容纳)。

您也可以查看 TIFF,但同样,这取决于数据的性质、网络带宽、所需的灵 active 、CPU 的编码/解码性能...

#!/usr/bin/env python3

import cv2
import numpy as np
import base64
import json
from io import BytesIO
from PIL import Image

def im2json(im):
    _, imdata = cv2.imencode('.JPG',im)
    jstr = json.dumps({"image": base64.b64encode(imdata).decode('ascii')})
    return jstr

def json2im(jstr):
    load = json.loads(jstr)
    imdata = base64.b64decode(load['image'])
    im = Image.open(BytesIO(imdata))
    return im

# Create solid red image 
red = np.full((480, 640, 3), [0, 0, 255], dtype=np.uint8)  

# Make image into JSON string
jstr = im2json(red)

# Extract image from JSON string into PIL Image
PILimage = json2im(jstr)
PILimage.show()

关于python - 以 JSON 格式发送 OpenCV 图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55892362/

相关文章:

python - 函数不返回值(Python 2.7)

objective-c - Obj-C/Swift 混合中的枚举和数组访问

python - 从 RGB 转换为 LAB 色彩空间——是否了解 L*A*B* 值的范围?

opencv - 如何使用 OpenCV 初始化多个 OpenNI 传感器

python - Opencv cv2.BFMatcher 没有看到相似之处

python - 运行最不常见子序列程序时出错

python - 使用正则表达式替换 json 中多余的引号

python - 简单的 SQLAlchemy 关系如何工作?

ios - AFNetworking 和 Swift

javascript - 如何从 flickr API 获取正确的 JSON 对象