Как вернуть dict + изображение из конечной точки FastAPI? - PullRequest
1 голос
/ 16 января 2020

Я пытаюсь использовать FastAPI, чтобы разрешить моему (закрепленному) серверу отвечать на вызовы API, возвращая

  • изображение image и
  • словарь additional_dict

(для примера машинного обучения это могут быть метки классификации из классификатора и карта значимости).

В моем случае, я думаю, что имеет смысл использовать одну и ту же конечную точку чтобы получить два объекта, потому что они генерируются с одинаковыми вычислениями.

Я могу успешно вернуть изображение в двоичном виде, используя что-то вроде { ссылка }:

from PIL import Image
from fastapi import FastAPI, File
import tempfile
from starlette.responses import FileResponse

@app.post("/getstuff")
async def get_image_and_data(file: bytes = File(...)):

    image, additional_dict = process_image(image)

    with tempfile.NamedTemporaryFile(mode="w+b", suffix=".png", delete=False) as outfile:
        image.save(outfile)
        return FileResponse(outfile.name, media_type="image/png")

Это позволяет мне даже видеть ответ изображения, когда я вызываю службу через пользовательский интерфейс swagger на localhost: 8000 / docs.

Однако я не знаю, как получить двоичный образ изображения и словарь вместе.

Я попытался заменить свое выражение return на:

return FileResponse(outfile.name, media_type="image/png"), additional_dict

, но это не сработало (при попытке получить swagger на localhost: 8000 / docs я просто получил json ответ ниже, с путем к созданному временному файлу)

[{
"path": "/tmp/tmpldwe_79d.png",
"status_code": 200,
"filename": null,
"send_header_only": false,
"media_type": "image/png",
"background": null,
"raw_headers": [
    [
    "content-type",
    "image/png"
    ]
],
"stat_result": null
},
{
"foo": 1,
"bar": 2
}]

Можно получить в ответе двоичное изображение и дополнительный dict из той же конечной точки? Если да, то как лучше это сделать?
Можно ли визуализировать изображение в Swagger UI /docs и прочитать там значения dict?

1 Ответ

2 голосов
/ 17 января 2020

Вы можете кодировать двоичные данные (в вашем случае это будет изображение) с помощью base64 и отправлять закодированную строку через словарь.

   import base64

   with open("image.png", "rb") as image_file:
       encoded_image_string = base64.b64encode(image_file.read())

   payload = {
       "mime" : "image/png",
       "image": encoded_image_string,
       "some_other_data": None
   }

Таким образом, этот словарь будет содержать закодированное изображение base64 и любые другие данные. fields.

На внешнем интерфейсе вы можете декодировать изображение из строки base64 обратно в байты и представить его пользователю.

...