问题
I have two thread classes extract and detect.
Extract extracts frames from a video and stores it in a folder, Detect takes images from the folder where frames are extracted and detects objects.
But when I run the below code only the extract works:
global q
q = Queue()
class extract(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
print("T1")
cam = cv2.VideoCapture(video_name)
frameNum = 0
# isCaptured = True
frameCount = 0
while True:
isCapture, frame = cam.read()
if not isCapture:
break
if frameCount % 5 == 0:
frameNum = frameNum + 1
fileName = vid + str(frameNum) + '.jpg'
cv2.imwrite('images/extracted/' + fileName, frame)
q.put(fileName)
frameCount += 1
cam.release()
cv2.destroyAllWindows()
class detect(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
print("T2")
#logic to detect objects.
if __name__ == '__main__':
thread1 = extract()
thread1.start()
thread2 = detect()
thread2.start()
This prints only T1 and no T2. I thought probably detect ran first and queue was empty so nothing happened so I added dummy entries into the queue and it ran how I wanted it to.
But it ran only for the dummy entries, it didn't work for the entries that the extract function added to the queue. Looked up other questions and none of them seemed to solve the problem, hence posting this here
回答1:
You probably want to keep your detect logic in infinite loop as well.
class detect(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
#detect frame
And if it is a single frame detection. Then consider waiting in detect thread.
from time import sleep
class detect(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
sleep(120)
# Detect logic
回答2:
Instead of waiting for a hardcoded time you can make use of Event()
and make your detect thread wait until the Event()
is set before performing the detection
If the event is set that means all tasks are done. Additionally, you also have to keep an eye on the queue if any tasks are there yet not processed.
I have written an example code to demonstrate how it works you can modify the code according to your needs.
Here extract
takes 5 seconds to add a task to queue and detect
checks for a task every 1 second. So if the extract is slower than also whenever something is available is will be processed by detect
. And when all tasks are done detect will break out of the loop.
import threading
import queue
import time
global q
q = queue.Queue()
class extract(threading.Thread):
all_tasks_done = threading.Event()
def __init__(self):
threading.Thread.__init__(self)
def run(self):
counter = 5
while counter:
time.sleep(5)
counter -= 1
q.put(1)
print("added a task to queue")
extract.all_tasks_done.set()
class detect(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while not extract.all_tasks_done.wait(1) or not q.empty():
print(q.get())
print("detection done")
#logic to detect objects.
if __name__ == '__main__':
thread1 = extract()
thread1.start()
thread2 = detect()
thread2.start()
thread1.join()
thread2.join()
print("work done")
来源:https://stackoverflow.com/questions/60204098/run-dependent-threads-simultaneously-in-python