Issue
I'm currently taking images from a webcam that should be processed as soon as they are captured. The code uses the cv2.videocapture() function.
Idea: As soon as an Image is captured I want to use the time the system needs to capture a new image for computation on the previous image.
To achieve this task I use the asyncio library.
First of all I define a producer function that produces n images which should be stored in a queue:
async def produce(queue, n):
for x in range(n):
# produce an item
print('producing {}/{}'.format(x, n))
# simulate i/o operation using sleep
await asyncio.sleep(random.random())
item = obtainImage()
z.append(x)
# put the item in the queue
await queue.put(item)
After that I implemented a consumer function which waits for an entry in the queue and computes some image features (here a simple threshold):
async def consume(queue):
while True:
# wait for an item from the producer
# Load the image stored in the queue
item = await queue.get()
# process the item and store value
ret,thresh1 = cv2.threshold(item,127,255,cv2.THRESH_BINARY)
# simulate i/o operation using sleep
await asyncio.sleep(random.random())
# Notify the queue that the item has been processed
queue.task_done()
#Return the Processesed image
return thresh1
To start the functions I created a run function and added it into an event loop (The run method contains a parameter of how many images i want to process):
async def run(n):
queue = asyncio.Queue()
# schedule the consumer
consumer = asyncio.ensure_future(consume(queue))
# run the producer and wait for completion
await produce(queue, n)
# wait until the consumer has processed all items
await queue.join()
# the consumer is still awaiting for an item, cancel it
consumer.cancel()
loop = asyncio.get_event_loop()
loop.run_until_complete(run(10))
print(loop)
loop.close()
As long as I use print statements I get an async output like this:
producing 0/10
producing 1/10
consuming 0...
producing 2/10
consuming 1...
producing 3/10
consuming 2...
producing 4/10
consuming 3...
Which is exactly what I desire in terms of order. However, I can`t get back any thresholded image. What am I missing?
Thank you in advance
Solution
Minimal example with global queue for results returning (tested with Python 3.5.2)
import asyncio
import random
outQ = asyncio.Queue()
async def produce(queue, n):
for x in range(n):
print('producing {}/{}'.format(x, n))
await asyncio.sleep(random.random())
item = x
await queue.put(item)
async def consume(queue):
while True:
print('consume ')
item = await queue.get()
thresh1 = item**2
print("... adding %d" % thresh1)
await outQ.put(thresh1)
await asyncio.sleep(random.random())
queue.task_done()
async def run(n):
queue = asyncio.Queue()
consumer = asyncio.ensure_future(consume(queue))
await produce(queue, n)
await queue.join()
consumer.cancel()
loop = asyncio.get_event_loop()
loop.run_until_complete(run(10))
loop.close()
while not outQ.empty():
print(outQ.get_nowait())
Output:
...
producing 9/10
... adding 64
consume
... adding 81
consume
0
1
4
9
16
25
36
49
64
81
Answered By - urban
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.