In my last tutorial I’ve shown you how to create a minimal Tkinter application: load an image with OpenCV, plot the image on a Tkinter window and apply a blur filter when the user presses a button. Another interesting application is to show a camera feed or an exiting video on a Tkinter window.
Please note that the video from the above screenshot is (c) copyright 2008, Blender Foundation www.bigbuckbunny.org, you can find it at this address, if you want to use it for tests.
We are going to start with a clean version of the last example from our previous tutorial:
the above code will show an empty Tkinter window.
Next, we’ll use the VideoCapture class from OpenCV to open a video, get the video width and height, and make sure that the video source is released when the object is destroyed:
We can use the read method of the VideoCapture class to get a frame from the video source:
Now, we can create a MyVideoCapture object inside the App class and using the video source width, height create a Canvas big enough to show the entire video:
If you run the above code, you should see an empty white window, big enough to show your webcam output. Closing the window will cleanly stop the webcam.
In order to actually see the camera output, we need to continuously get frames from the camera and plot these on the Canvas object. In a typical OpenCV application, you could write an infinite loop and get frames from the camera until the user closes the window. This is not advisable when mixing Tkinter with OpenCV! Tkinter, like most GUI libraries, has his own infinite loop that processes events and redraws the application window. A clean solution, that integrates well with Tkinter is to add an update method for the App class that is also passed to the after method of a Tkinter widget. In our case, we’ll use the window widget for this:
If you call the update method once, it will be registered as a callback function, by the window widget after method, and will be called every delay milliseconds. We can call the update method in the init method before starting the mainloop:
Now, that we have an update mechanism in place, we can get frames from the video source in the update method and plot these on the Canvas:
At this point, if you run the code, you should see the camera output drawn in the Tkinter window.
Like in our previous tutorial, let’s add a button that when pressed will do something with the video output. We can save the current video frame when the user presses this button. Add the button initialization code just before calling the update method:
When the Snapshot button is pressed, the snapshot method will be called. Let’s write the code for the snapshot method:
By default, the snapshots will be saved in the current directory with a time stamp.
If you pass the path to a video to the App object, you will see the video in the Tkinter window, instead of your webcam. E.g., I have a video named big_buck_bunny_480p_surround-fix.avi on my system, if I pass this to the App:
you should see an image like the one from the beginning of this article.
Here is the full source code for this example:
As an exercise, you can add the capability to save the video in a separate file. This could be useful if you want to record the output of your webcam.