繁体   English   中英

无法解码 base64 编码图像

[英]Not able to decode base64 encoded image

我是 python 的新手。 我的任务是构建一个 API 端点,该端点获取图像并返回图像。 所以,我选择了flask来完成我的工作。

我遵循了这个 SO 问题 - 基于烧瓶的 API 是否可以为 API 端点返回文件以上传图像文件。

代码如下:

from flask import Flask, render_template , request , jsonify
from PIL import Image
import os , io , sys
import numpy as np 
import cv2
import base64

app = Flask(__name__)

start_point = (0, 0) 
end_point = (110, 110) 
color = (255, 0, 0)
thickness = 2

@app.route('/image' , methods=['POST'])
def mask_image():
    file = request.files['image'].read()
    npimg = np.fromstring(file, np.uint8)
    img = cv2.imdecode(npimg,cv2.IMREAD_COLOR)
    img = Image.fromarray(img.astype("uint8"))
    rawBytes = io.BytesIO()
    img.save(rawBytes, "png")
    rawBytes.seek(0)
    img_base64 = base64.b64encode(rawBytes.read())
    return jsonify({'status':str(img_base64)})


if __name__ == '__main__':
    app.run(debug = True)

然后我使用python requests file upload向 API 发送请求。

但我无法解码 base64 响应。 我试过的代码

import requests
import base64

files = {'image': open('image.png','rb')}
r = requests.post("http://localhost:5000/image", files=files)
print(base64.decodestring(r.text))

但它抛出一个错误

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/anaconda3/envs/py37/lib/python3.7/base64.py in _input_type_check(s)
    509     try:
--> 510         m = memoryview(s)
    511     except TypeError as err:

TypeError: memoryview: a bytes-like object is required, not 'str'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
<ipython-input-192-e8ba5f9daae3> in <module>
----> 1 base64.decodestring(r.text)

~/anaconda3/envs/py37/lib/python3.7/base64.py in decodestring(s)
    552                   "use decodebytes()",
    553                   DeprecationWarning, 2)
--> 554     return decodebytes(s)
    555
    556

~/anaconda3/envs/py37/lib/python3.7/base64.py in decodebytes(s)
    543 def decodebytes(s):
    544     """Decode a bytestring of base-64 data into a bytes object."""
--> 545     _input_type_check(s)
    546     return binascii.a2b_base64(s)
    547

~/anaconda3/envs/py37/lib/python3.7/base64.py in _input_type_check(s)
    511     except TypeError as err:
    512         msg = "expected bytes-like object, not %s" % s.__class__.__name__
--> 513         raise TypeError(msg) from err
    514     if m.format not in ('c', 'b', 'B'):
    515         msg = ("expected single byte elements, not %r from %s" %

TypeError: expected bytes-like object, not str

如何解码图像?

两件事,首先base64.decodestring需要字节,而不是字符串。 您需要使用r.contentr.text.encode('utf8')来获取字节。 同样, decodestring已被弃用,因此您不应使用它。 通常,除非您有充分的理由不这样做,否则您应该使用base64.b64decode来解码 base64 数据。

其次, /image端点返回包含 base64 图像的 JSON object。 您的客户端必须首先从 JSON 响应中提取图像数据,然后对其进行解码。 response object 包含一个对此有用的 .json .json()方法:

import requests
import base64

files = {'image': open('image.png','rb')}
r = requests.post("http://localhost:5000/image", files=files)
print(base64.b64decode(r.json()['status']))

标记的答案是我自己的。 因此,我将提供答案。

其中一位用户@ToxicCode 已经给出了 99% 的答案。 但这里有一个问题。 该脚本将响应作为包装在如下字符串中的字节字符串发送。

"b'iVBORw0KGgoAAAANSUhEUgAABXYAAAOOCAIAAAAru93tAAEAAElEQVR4nOz9eZRk+V3ffX5+98a+ZkbutbZ2gZAx6DFgsEGHHRtrsC0xFgezGGg3to8H2+NlQGjmSAI/D4wfGD/40AiZRTDgBwkMGI9AwjoCzGLZgLHYZEmou5bMjFwiMjPWu37nj4iqzOqur
...
..

字节b已经存在于字符串中。 因此,如果您遵循@ToxicCode 而不注意这一点,您将面临错误。 因此,作为一种不好的方法,您可以使用ast.literal_eval转换为字符串,然后遵循@ToxicCode 代码。

重要提示:不要在生产服务器中使用ast.literal_eval() 相应地更改实现。

import ast
import requests
import base64

files = {'image': open('image.png','rb')}
r = requests.post("http://localhost:5000/image", files=files)
data = ast.literval_eval(r.json()['status'])
print(base64.b64decode(data))

尝试r.content是字节而不是r.text是一个字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM