Я разработал программу производитель-потребитель в Python с одним производителем (который считывает кадры с камеры на высокой скорости) и двумя потребителями (один для отображения видео в формате * 1003). * cv2 window , а другой для сохранения каждого кадра на диск). Три потока связаны двумя очередями (q1 и q2), по одной для каждого потребителя, поскольку ничто не должно блокировать получение и отображение изображения. Я пробовал эту часть самостоятельно, и она отлично работает. Здесь я адаптировал код класса, так что получение теперь "подделывается" путем помещения фреймов с нулями в очереди.
import multiprocessing
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import PIL.Image, PIL.ImageTk
import cv2
from threading import Thread,Lock,Semaphore
import queue
import time
from tifffile import imsave
import numpy as np
import os
class VideoGet():
def __init__(self,folder,record):
self.record = record
self.counter=0
self.folder = folder
def displayer(self,q2):
while q2.empty() is False:
framedisplay = q2.get()
cv2.imshow("Video", framedisplay)
cv2.waitKey(1)
q2.task_done()
cv2.destroyAllWindows()
def consumer(self,q):
while q.empty() is False:
frame_get = q.get()
imsave(os.path.join(self.folder,(str(self.counter)+'.tiff')), frame_get)
self.counter=self.counter+1
q.task_done()
def producer(self,buffer,q,q2):
while self.record is True:
frame=np.zeros_like(buffer)
q.put(frame)
q2.put(frame)
del frame
def run(self,buffer,q,q2):
prod_thread=Thread(target=self.producer,args=(buffer,q,q2,))
display_thread=Thread(target=self.displayer,args=(q2,))
con_thread= Thread(target=self.consumer, args=(q,))
prod_thread.start()
display_thread.start()
con_thread.start()
prod_thread.join()
display_thread.join()
con_thread.join()
Я хочу создать небольшой tkinter GUI всего с тремя кнопками, одна запрос папки, другой для начала сбора данных (при этом появится окно cv2) и последний для остановки и полного уничтожения системы. Я разработал класс, который вызывает потоки при правильном нажатии кнопок. Появляется cv2 windows и кадры сохраняются, но GUI зависает и больше не отвечает, поэтому я больше не могу нажимать кнопку «Стоп» . Я предполагаю, что проблемы в том, что потоки не работают так, как я ожидал.
Есть идеи, как правильно найти или вызвать потоки ?. И, может быть, как отображать кадры в GUI вместо этого, а не в окне cv2?
PS: Я знаю, что это немного длинный код, но я не знал, как его лучше сжать
class VideoGUI():
def __init__(self, window, window_title):
self.window = window
self.window.title(window_title)
bottom_frame = Frame(self.window)
bottom_frame.pack(side=BOTTOM, pady=5)
self.record = True # Parameter that controls pause button
self.btn_select=Button(bottom_frame, text="Select a folder", width=15, command=self.open_file)
self.btn_select.grid(row=0, column=0)
# Play Button
self.btn_play=Button(bottom_frame, text="Play", width=15, command=self.play_video)
self.btn_play.grid(row=0, column=1)
# Pause Button
self.btn_pause=Button(bottom_frame, text="Stop", width=15, command=self.pause_video)
self.btn_pause.grid(row=0, column=2)
self.buffer=np.zeros(shape=(513,640), dtype=np.uint16)
self.disp_queue=queue.Queue()
self.save_queue=queue.Queue()
self.window.mainloop()
def open_file(self):
self.folder=filedialog.askdirectory(title="Select folder")
self.video_object=VideoGet(self.folder,self.record)
def play_video(self):
try:
self.video_object.run(self.buffer,self.save_queue,self.disp_queue)
except:
print('no play')
def pause_video(self):
try:
self.video_object.record=False
except:
self.window.destroy()
# Create a window and pass it to videoGUI Class
if __name__=='__main__':
video_object=VideoGUI(Tk(),"camera")