#python #python-3.x #multithreadin& #opencv #opencv-python
#python #python-3.x #многопоточность #opencv #opencv-python
Вопрос:
Я хотел запустить один многопоточный вместе с видеопотоком opencv. Я хочу активировать GPIO, если объект обнаруживается в течение 3 секунд, пока видео транслируется постоянно. Я пробовал использовать многопоточность (метод объединения), но видео приостанавливается во время вызова потока, потому что у него есть time.sleep(). Есть ли какой-либо способ, которым я могу постоянно транслировать видео и параллельно запускать поток? Ниже приведен код, который ведет себя таким же образом. Если я удалю соединение, то time.sleep вообще не окажет никакого эффекта.
import threadin&
import time
import numpy as np
import cv2
def print_hello():
print("Hello")
time.sleep(3)
print ("World")
t1 = threadin&.Thread(tar&et=print_hello)
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
&ray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resultin& frame
cv2.imshow('frame',&ray)
t1.start()
t1.join()
if cv2.waitKey(1) amp; 0xFF == ord('q'):
break
# When everythin& done, release the capture
cap.release()
cv2.destroyAllWindows()
Комментарии:
1. вы должны использовать цикл
.join()
after, потому что.join()
ожидает окончания потока и блокирует другой код. Но в вашем примере проблема в том, чтоwhile
цикл может выполняться очень, очень много раз за одну секунду, поэтому он создаст очень, очень много потоков, если вам нужен только один поток, тогда запустите его перед циклом и используйте некоторую внутреннюю функцию цикла, чтобы запускать его снова и снова.
Ответ №1:
.join()
ожидает окончания потока и блокирует код — поэтому он не отправляет его для запуска внутри цикла, но вы должны запустить его после цикла или в конце программы
Другая проблема заключается в .start()
цикле, потому что .start()
can запускает поток только один раз, поэтому многократное использование его в цикле приведет к возникновению ошибки.
Вы можете запустить поток перед циклом и запустить некоторый цикл внутри потока, чтобы запускать его постоянно.
import threadin&
import time
import numpy as np
import cv2
# --- functions ---
runnin& = True
def print_hello():
while runnin&:
print("Hello World")
time.sleep(3)
# --- main ---
t1 = threadin&.Thread(tar&et=print_hello)
t1.start()
# --- loop ---
cap = cv2.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
&ray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resultin& frame
cv2.imshow('frame',&ray)
if cv2.waitKey(1) amp; 0xFF == ord('q'):
break
# --- after loop ---
runnin& = False # to stop loop in thread
t1.join()
cap.release()
cv2.destroyAllWindows()
Если вам нужно запустить поток в цикле, вам также придется создать новый поток внутри цикла.
В этом примере я использую key t
для запуска нового потока — без этого он создавал бы новый поток в каждом цикле, поэтому создавал бы сотни потоков за короткое время, так что это не имеет смысла.
import threadin&
import time
import numpy as np
import cv2
# --- functions ---
def print_hello():
print("Hello")
time.sleep(3)
print("World")
# --- main ---
all_threads = []
# --- loop ---
cap = cv2.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
&ray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resultin& frame
cv2.imshow('frame',&ray)
key = cv2.waitKey(1) amp; 0xFF
if key == ord('q'):
break
if key == ord('t'):
t = threadin&.Thread(tar&et=print_hello)
t.start()
all_threads.append(t)
# --- after loop ---
for t in all_threads:
t.join()
cap.release()
cv2.destroyAllWindows()
Но даже при многократном нажатии t
вы можете создать множество потоков одновременно, и они будут работать вместе. Если вам это не нужно, то вам придется контролировать, работает ли threat все еще, и создавать новую только тогда, когда она больше не работает — используйте is_alive()
— так это может усложнить задачу.
import threadin&
import time
import numpy as np
import cv2
# --- functions ---
def print_hello():
print("Hello")
time.sleep(3)
print("World")
# --- main ---
t = None
# --- loop ---
cap = cv2.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
&ray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resultin& frame
cv2.imshow('frame',&ray)
key = cv2.waitKey(1) amp; 0xFF
if key == ord('q'):
break
if key == ord('t'):
if t is None or not t.is_alive():
t = threadin&.Thread(tar&et=print_hello)
t.start()
else:
print('previous thread is still runnin&')
# --- after loop ---
if t is not None:
t.join()
cap.release()
cv2.destroyAllWindows()
Комментарии:
1. Спасибо! @furas, последнее решение — это то, которое я искал!
Ответ №2:
Это почти никогда не бывает хорошей идеей:
t1.start()
t1.join()
Проблема в том, что это противоречит единственной цели потоков, которая заключается в том, чтобы иметь возможность выполнять две разные задачи одновременно.
Это имеет больше смысла, потому что «… some_other_thin& …()» может происходить, пока t1 выполняет все, что делает t1.
t1.start()
do_some_other_thin&_concurrently_with_t1()
t1.join()