pythonjsonflaskjsonify

how to pass a json String to a url using Flask


I did create a machine learning model using Pytorch which i want to use as a webservice using Flask. The problem is that i don't understand how i can pass a json-String to the url. Below is my code that I wrote to do some tryouts with my model and Flask:

from modelLoader import Model
from imageLoader import Img
import os
from flask import Flask, jsonify, request

app = Flask(__name__)
classes = ["dummy-image", "product-image"]
model_path = os.path.join("data", "models", "model1709", "model1709")
image_path = os.path.join("data", "images", "dummy_images")
m1 = Model(model_path, classes, "cpu")

@app.route('/predict', methods=['POST', 'GET'])
def predict():
    # case for handle json
    input_data = request.get_json()['url']
    if isinstance(input_data, list):
        for elem in input_data:
            img_elem = Img(url=elem)
            res = img_elem.get_prediction(m1)
        return jsonify({"type": "bulk_upload"})
    img_inpdata = Img(url=input_data)
    res, info = img_inpdata.get_prediction(m1)
    return jsonify({input_data: res, "info": str(info)})


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

This would be a request that I want to make using this code:

POST http://192.168.178.13:5000/predict HTTP/1.1
Content-Type: application/json
Accept: application/json

{
    "url" : "https://socialistmodernism.com/wp-content/uploads/2017/07/placeholder-image.png"
}

How exactly can I get the prediction for the image inside the json-string, by passing this json-string to the application?


Here the two classes model and imageLoader for completeness:

from torch import argmax, device, load, nn

class Model:
    def __init__(self, path, class_list=None, dvc=None):
        if class_list is None:
            class_list = [0, 1]
        if dvc is None:
            dvc = 'cpu'
        self.class_list = class_list 
        self.model = load(path, map_location=device(dvc))
        num_ftrs = self.model.fc.in_features                  
        self.model.fc = nn.Linear(num_ftrs, len(class_list))  
        self.model.eval()

import torchvision.transforms as transforms
import io
from PIL import Image
from torch import argmax, device, load, nn
import requests

class Img:
    def __init__(self, url=None, image=None, image_bytes=None):
        if url:
            img = Image.open(requests.get(url, stream=True).raw)
            img_byte_arr = io.BytesIO()
            img.save(img_byte_arr, format=img.format)
            self.image_bytes = img_byte_arr.getvalue()
        elif image:
            f = image.read()
            self.image_bytes = bytearray(f)
        elif image_bytes:
            self.image_bytes = image_bytes

    def transform_image(self):
        data_transforms = transforms.Compose([transforms.Resize((224, 224)),
                                              transforms.CenterCrop(
                                                  224), transforms.ToTensor(),
                                              transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224,
                                                                                           0.225])])
        image = Image.open(io.BytesIO(self.image_bytes)).convert('RGB')
        return data_transforms(image).unsqueeze(0)

    def get_prediction(self, model):
        tensor = self.transform_image()
        output = (model.model(tensor))
        sm = nn.Softmax(output)
        best = output.argmax().item()
        return model.class_list[best], sm

Solution

  • You cannot do a POST request directly from the browser URL box. There are many applications to test your API and my favorite one is postman. You can also use the curl command tool.

    If you want to use the browser URL box only, then consider using the GET request. The format of GET request is <URL>?parameter1=value1&parameter2=value2. You can access the value of the parameter in flask using the request module. For example, if your service is at http://192.168.178.13:5000/predict. You can send it as http://192.168.178.13:5000/predict?url=your-url. And you can fetch it in flask as

    from flask import request
    my_url = request.args.get("url")