K41*_*F4r 3 python base64 json opencv python-imaging-library
我正在尝试以 json 格式发送 OpenCV 图像并在另一端接收它,但在编码和解码图像时遇到了无穷无尽的问题
我通过以下方式以 JSON 形式发送它:
dumps({"image": b64encode(image[y1:y2, x1:x2]).decode('utf-8')})
Run Code Online (Sandbox Code Playgroud)
在另一端,我尝试解码它(我需要它作为枕头图像):
image = Image.open(BytesIO(base64.b64decode(data['image'])))
Run Code Online (Sandbox Code Playgroud)
但我越来越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)
Run Code Online (Sandbox Code Playgroud)
但后来我'NoneType' object has no attribute '__array_interface__'来自Image.fromarray
有什么想法我做错了吗?
希望这可以帮助您入门。我认为您尝试通过从 Numpy 数组发送未修饰的字节可能行不通,因为接收器不知道图像中的宽度、高度和通道数,所以我用来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()
Run Code Online (Sandbox Code Playgroud)
由于您没有在评论中回答我关于为什么要这样做的问题,因此它可能不是最佳的 - 通过网络发送未压缩的、base64 编码的图像(大概)效率不高。例如,您可能会考虑使用 JPEG 或 PNG 编码数据来节省网络带宽。
您也可以使用cPickle代替。
请注意,有些人不赞成pickle,而且上述方法使用了大量的网络带宽。另一种方法可能是在发送之前对图像进行 JPEG 压缩,并在接收端直接解压缩为 PIL 图像。请注意,这是有损的。
或者将.JPG代码中的扩展名更改为.PNG无损但可能速度较慢,并且不适用于具有浮点数据或 16 位数据的图像(尽管可以容纳后者)。
您也可以查看 TIFF,但同样,这取决于数据的性质、网络带宽、所需的灵活性、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()
Run Code Online (Sandbox Code Playgroud)