Abhishek Rai
Abhishek Rai

Reputation: 2227

Cannot Process decoded Image files, Flask, OpenCV

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.

Upvotes: 0

Views: 574

Answers (1)

Detlef
Detlef

Reputation: 8552

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')

Upvotes: 1

Related Questions