I am making a simple GUI for a video capture application using customtkinter and opencv. The code below is the creation and start of the thread which is responsible for executing the video capture function. This code is inside the initialization of my application class:
class App(customtkinter.CTk):
def __init__(self):
...
self.stopEvent = threading.Event()
self.thread = threading.Thread(target=self.videoLoop, args=())
self.thread.start()
...
the function for the actual video capturing is:
def videoLoop(self):
while True:
if self.stopEvent.is_set() == True:
cap.release()
cv2.destroyAllWindows()
break
ret, frame = cap.read()
img = cv2.rectangle(frame, (380, 80), (1540,950), (0,0,255),2)
#add vertical line
img2 = cv2.line(img, (960, 85), (960,945), (0,255,0),1)
#add horizontal line
img3 = cv2.line(img2, (400, 515), (1520,515), (0,255,0),1)
#get frame rate
fps = int(cap.get(cv2.CAP_PROP_FPS))
#add frame rate text
disp_frame = cv2.putText(img3, "FPS: " str(fps), (0, 50), cv2.FONT_HERSHEY_PLAIN, 4, (100, 255, 0), 2)
conv_img = cv2.cvtColor(disp_frame, cv2.COLOR_BGR2RGB)
conv_img = Image.fromarray(conv_img)
conv_img = ImageTk.PhotoImage(image=conv_img)
self.videoframe.create_image(500,500,image=conv_img,anchor="s")
self.videoframe.image = conv_img
upon exiting the application, the on_closing is executed for the clean-up:
def on_closing(self):
self.stopEvent.set()
self.destroy()
The issue with this one is that when I try to exit the app, the thread that handles the video capturing seems to not terminate properly as I cannot interact with my VSCode terminal requiring me to run a new instance of the terminal before I can run my application again. Is there a specific way to stop the thread?
CodePudding user response:
Maybe you are perceiving a runtime issue. When this gets executed:
def on_closing(self):
self.stopEvent.set()
self.destroy()
Is it possible that self got detroyed before the other thread had a chance to properly finish?
In that case do not destroy the object immediately. Wait for a signal from the background thread that it has stopped processing, then run destroy.
CodePudding user response:
I found a workaround for the thread issue. Instead of initializing and starting the thread inside the App class, I created it inside the top-level code which now looks like this (btw, I renamed the videoLoop
function into thread_loop:
if __name__ == "__main__":
app = App()
thread = threading.Thread(target=app.thread_loop,args=())
thread.start()
app.mainloop()
thread.join()
and my on_closing function
def on_closing(self):
cap.release()
self.destroy()
I'm not sure if this is best solution but the thread now terminates properly