Ad

Should I Use Asyncio Or Thread Pool For Gain Performance In Api Requests?

I want to make a real time face recognizer with azure cognitive service's face api. But the api calls takes so much time. What concept should I use in that situation?

I wrote my code in the simple while loop. Grap a frame and detect faces in that frame. But the request part for detection faces is takes ~2.5 seconds. So, it's soooo far from real time detection :) I found a c# example at their website but i couldn't handle. The link is : https://docs.microsoft.com/en-us/azure/cognitive-services/face/face-api-how-to-topics/howtoanalyzevideo_face

while True:
    image = getCapture()
    cv2.imshow('image', image)
    image = cv2.imencode('.jpg', image)[1].tostring()
    response = requests.post(vision_analyze_url,
                             params=params,
                             headers=headers,
                             data=image)
    print(response.json())
    key = cv2.waitKey(1) & 0xFF

I want to make this real time but I think it's impossible :/ So I can save video and make requests with batches of this images, or I can make this two jobs simultaneously. What can I do? I have to do that in 2 days :D

Ad

Answer

But the request part for detection faces is takes ~2.5 seconds. [...] I want to make this real time

You could submit requests in parallel to increase processing throughput. To upgrade from the current 0.4 fps to 25 fps (real-time), you would have to submit ~625 requests in parallel. You'd still have a latency of 2.5s, but the delay would be constant. Unless your backend has 600+ cores, or it's running on a cluster, this is unlikely to work. But if you want to try, the code that runs requests in parallel could look like this:

import concurrent.futures, itertools, functools

pool = concurrent.futures.ThreadPoolExecutor(max_workers=1000)

def on_complete(frameno, future):
    response = future.result()
    print(frameno, response.json())

for frameno in itertools.count(start=1):
    image = getCapture()
    cv2.imshow('image', image)
    image = cv2.imencode('.jpg', image)[1].tostring()
    future = pool.submit(lambda: requests.post(vision_analyze_url,
        params=params, headers=headers, data=image))
    future.add_done_callback(functools.partial(on_complete, frameno))
    key = cv2.waitKey(1) & 0xFF

This uses threads; asyncio is not a good fit for this problem because you are using the non-async cv2 library which would block the event loop.

Ad
source: stackoverflow.com
Ad