0

I am receiving a bunch of images to the flask app via the client file.

client.py

# Generate the parallel requests based on the ThreadPool Executor
from concurrent.futures import ThreadPoolExecutor as PoolExecutor
import sys
import time
import glob
import requests
import threading
import uuid
import base64
import  json
import os

#send http request
def call_object_detection_service(image):
    try:

        url = str(sys.argv[2])
        data = {}
        #generate uuid for image
        id = uuid.uuid5(uuid.NAMESPACE_OID, image)
        # Encode image into base64 string
        with open (image, 'rb') as image_file:
            data['image'] =  base64.b64encode(image_file.read()).decode('utf-8')

        data['id'] = str(id)
        headers = {'Content-Type': 'application/json'}

        response = requests.post(url, json= json.dumps(data), headers = headers)

        if response.ok:
            output = "Thread : {},  input image: {},  output:{}".format(threading.current_thread().getName(),
                                                                        image,  response.text)
            print(output)
        else:
            print ("Error, response status:{}".format(response))

    except Exception as e:
        print("Exception in webservice call: {}".format(e))

# gets list of all images path from the input folder
def get_images_to_be_processed(input_folder):
    images = []
    for image_file in glob.iglob(input_folder + "*.jpg"):
        images.append(image_file)
    return images

def main():
    ## provide argumetns-> input folder, url, number of wrokers
    if len(sys.argv) != 4:
        raise ValueError("Arguments list is wrong. Please use the following format: {} {} {} {}".
                         format("python iWebLens_client.py", "<input_folder>", "<URL>", "<number_of_workers>"))

    input_folder = os.path.join(sys.argv[1], "")
    images = get_images_to_be_processed(input_folder)
    num_images = len(images)
    num_workers = int(sys.argv[3])
    start_time = time.time()
    #craete a worker  thread  to  invoke the requests in parallel
    with PoolExecutor(max_workers=num_workers) as executor:
        for _ in executor.map(call_object_detection_service,  images):
            pass
    #elapsed_time =  time.time() - start_time
    #print("Total time spent: {} average response time: {}".format(elapsed_time, elapsed_time/num_images))


if __name__ == "__main__":
    main()

I decode them like so Flask App

app = Flask(__name__)

c = 1
@app.route('/api/object_detection', methods = ['POST'])
def main():
    global c
    try:
        data = request.get_json(force=True)
        uid = data.get('id')
        image = data.get('image')
        print(image)
        im = base64.decodebytes(image)
        with open("image{}".format(c), 'wb') as f:
            f.write(im)
        c += 1
        for l in range(128):
            img = cv2.imread("image{}".format(l), cv2.IMREAD_ANYCOLOR);
            # load the neural net.  Should be local to this method as its multi-threaded endpoint
            nets = load_model(CFG, Weights)
            s = do_prediction(img, nets, Lables)
            return jsonify(s)

    except Exception as e:
        print(e)




if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True, threaded=True)

This creates the image files with different sizes but I cannot view them in image viewer. The files being recieved are jpg files. Ignoring that, I went ahead with the processing and I get

TypeError: The view function for 'main' did not return a valid response. The function either returned None or ended without a return statement.
Incorrect padding
Incorrect padding
[INFO] loading YOLO from disk...
'NoneType' object has no attribute 'shape'

Images are being sent like this.

python iWebLens_client.py inputfolder/ http://192.168.29.75:5000/api/object_detection 4

The images are being received like this.

b'"{\\"image\\": \\"/9j/4AAQSkZJRgABAQEASABIAAD/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA......fiU05tQopHNf//Z\\", \\"id\\": \\"e3ad9809-b84c-57f1-bd03-a54e25c59bcc\\"}"'

I am thinking I need to decode('utf-8') this, but don't know how.

3
  • image = request.data -- but your client is sending a JSON string, not just the image... Commented Apr 19, 2021 at 18:37
  • request.data is the raw data (notice the b) in front of your "string". You probably don't want to manage the raw data yourself. Thankfully, flask can handle this for you. See this answer for details on how to get formatted data from a request. You will likely be able to do request['image'] to get your image data. Then you need to decode it based on however it was encoded. Commented Apr 19, 2021 at 19:43
  • @noslenkwah There is no way to do request['image']. The client sends json, which becomes string, even if I get the image value, encode and then decode it, it still doesn't work. Just jumping between, should be bytes not str error messages. Commented Apr 19, 2021 at 19:52

1 Answer 1

1

Currently, you are double-coding the data on the client side. Within requests, the argument passed is already converted to JSON.

Just pass the dict on as a json parameter.

def call_object_detection_service(image):
    try:

        url = str(sys.argv[2])
        data = {}
        #generate uuid for image
        id = uuid.uuid5(uuid.NAMESPACE_OID, image)
        # Encode image into base64 string
        with open (image, 'rb') as image_file:
            data['image'] =  base64.b64encode(image_file.read()).decode('utf-8')

        data['id'] = str(id)
        headers = {'Content-Type': 'application/json'}

        # HERE IS THE CHANGE !!!
        response = requests.post(url, json=data, headers=headers)

        if response.ok:
            output = "Thread : {},  input image: {},  output:{}".format(
                threading.current_thread().getName(),
                image, 
                response.text
            )
            print(output)
        else:
            print ("Error, response status:{}".format(response))

    except Exception as e:
        print("Exception in webservice call: {}".format(e))

The data can now be received on the server as JSON and extracted into a dict.

@app.route('/api/object_detection', methods=['POST'])
def main():
    data = request.get_json(force=True)
    uid = data.get('id')
    image = data.get('image')
    # ... decode the base64 data here ...
    return jsonify(message='done')
Sign up to request clarification or add additional context in comments.

9 Comments

I did try this. 'str' object has no attribute 'get' . json beomes a string, it needs bytes. You cannot access the values like that. I had to add the incoming json to a list, then I can access the image value. Even that wouldn't be decoded because , again it is a string.
@AbhishekRai Because you convert a dict on the client side into a JSON string which is converted again into JSON.
@AbhishekRai This is how it works for me. I hope and think it should work for you too, otherwise leave me a comment.
The issue is not getting the image string, but decoding it. It is being a string every time it needs bytes, that's the problem, let me just update the code with your implentation in the question. the error again is expected bytes-like object, not str
If I encode the string and then decode it, the error goes , but then the original error in the question appears 'NoneType' object has no attribute 'shape' , The Image files are created, they have size, but get treated as None type objects. Oh! the padding error is gone as well.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.