7

I get an image, change it, then it is classified using a neural network, should return a new image and json with a response. How to do it with one endpoint? image is returned with Streaming Response but how to add json to it?

import io
from starlette.responses import StreamingResponse

app = FastAPI()

@app.post("/predict")
def predict(file: UploadFile = File(...)):
    img = file.read()
    new_image = prepare_image(img)
    result = predict(new_image)
    return StreamingResponse(io.BytesIO(new_image.tobytes()), media_type="image/png")
pavel hrablis
  • 131
  • 1
  • 7
  • Can you provide what your desired json response looks like? – phyominh Feb 18 '21 at 18:22
  • json of this kind : { 'objects': { 'object1': { 'x' : 5 , 'y': 3 }, 'object2': { 'x' : 5 , 'y': 3 }}} – pavel hrablis Feb 18 '21 at 18:34
  • What is `objects`, what does represent `x` and `y` (you have 2 times the same coordinates) ? – Fabien Sa Feb 18 '21 at 21:52
  • this is just an example of what json looks like, objects and x, y have nothing to do with the question, the question is how to send the response image and this json together – pavel hrablis Feb 18 '21 at 22:11
  • 2
    [Possible solution](https://stackoverflow.com/questions/59760739/how-do-i-return-a-dict-an-image-from-a-fastapi-endpoint) – phyominh Feb 19 '21 at 04:23

2 Answers2

6

I added json to response headers. change from:

@app.post("/predict")
def predict(file: UploadFile = File(...)):
    img = file.read()
    new_image = prepare_image(img)
    result = predict(new_image)
    return StreamingResponse(io.BytesIO(new_image.tobytes()), media_type="image/png")

to

@app.post("/predict/")
def predict(file: UploadFile = File(...)):
    file_bytes = file.file.read()
    image = Image.open(io.BytesIO(file_bytes))
    new_image = prepare_image(image)
    result = predict(image)
    bytes_image = io.BytesIO()
    new_image.save(bytes_image, format='PNG')
    return Response(content = bytes_image.getvalue(), headers = result, media_type="image/png")
pavel hrablis
  • 131
  • 1
  • 7
1

I was having the same issue, although, my file was stored locally but still I have to return JSON, and Image in a single response.

This worked for me, much neater and shorter:

@app.post("/ImgAndJSON")
# Postmsg is a Pydantic model having 1 str field
def ImgAndJSON(message:PostMsg):

    results={"message":"This is just test message"}

    return FileResponse('path/to/file.png',headers=results)
PankajSanwal
  • 956
  • 7
  • 14