Binocular camera driver interface based on Python and Tkinter

Article directory

    • Preface
    • Preparation
    • code analysis
      • initialization
      • Create button
      • Create image display area
      • Create information labels
      • Start camera capture
      • main function
      • in conclusion
      • Show results

Foreword

This article will introduce how to use Python and Tkinter library to create a simple camera application. This application opens the camera, displays the image captured by the camera, and allows the user to take snapshots.

Preparation

The following Python libraries need to be installed:
tkinter: used to create GUI interfaces.
cv2: OpenCV library for processing images and capturing camera frames.
PIL: Python Imaging Library for image processing.
numpy: used for numerical calculations.

Code analysis

The program consists of a MyWindow class, which contains the main logic and GUI elements of the application.

Initialization

class MyWindow:
    def __init__(self, root):
        self.root = root
        root.title("Camera")
        root.geometry("960x640")
        #...

Created a MyWindow class that creates a Tkinter window during initialization and sets the window title and size.

Create button

 def create_buttons(self):
        #...

Two buttons are created, one to initiate camera capture and the other to take a snapshot.

Create image display area

def create_image_displays(self):
        #...

Create two Canvas to display the left and right half of the image captured by the camera.

Create information tags

def create_info_label(self):
    #...

A Label is created to display interactive information, such as the file name of the snapshot taken.

Start camera capture

def start_capture(self):
    while True:
        ret, frame = self.camera.read()
        #...

This method starts the camera capture loop, which continuously captures camera frames and displays them on the left and right Canvas.
Take a snapshot

def take_snapshot(self):
      #...

This method allows the user to take a snapshot, save the left and right halves of the image as PNG files, and display the saved file names on the information label.

Main function

def main():
    root = tk.Tk()
    my_window = MyWindow(root)
    root.mainloop()

if __name__ == "__main__":
    main()

In the main function, the Tkinter window is created and the MyWindow class is instantiated, and then Tkinter’s main loop is started.

Conclusion

With the above code and explanation, it is possible to create a simple camera application that captures images and saves snapshots. You can extend the application as needed to add more features, such as image processing, etc.

Effect display

run

start up

shooting

The complete program code is as follows:

import tkinter as tk
from tkinter import Canvas, Label, Button
import cv2
import numpy as np
from PIL import Image, ImageTk
import os
from PIL import Image

class MyWindow:
    def __init__(self, root):
        self.root = root
        root.title("Camera")
        root.geometry("960x640")

        self.create_buttons()
        self.create_image_displays()
        self.create_info_label()
        self.camera = cv2.VideoCapture(0) #Open the camera
        self.left_photo = tk.PhotoImage()
        self.right_photo = tk.PhotoImage()
        self.snapshot_count = 0 # Used to increment the file name number

    def create_buttons(self):
        #Create a frame for horizontally centered buttons
        button_frame = tk.Frame(self.root)
        button_frame.pack(side="top")

        #Create a shooting button and bind the event handler function
        self.capture_button = tk.Button(button_frame, text="Start", width=10, height=2, command=self.start_capture)
        self.capture_button.pack(side="left", padx=10, pady=20)

        #Create a capture button
        self.start_button = tk.Button(button_frame, text="take", width=10, height=2, command=self.take_snapshot)
        self.start_button.pack(side="left", padx=10)

    def create_image_displays(self):
        #Create a frame to accommodate two Canvas and arrange them horizontally in the center
        image_frame = tk.Frame(self.root)
        image_frame.pack(side="top", pady=20) # Add vertical spacing to center it vertically

        #Create the Canvas on the left and set the background color to white
        self.left_canvas = Canvas(image_frame, width=320, height=240, bg="white")
        self.left_canvas.pack(side="left", padx=20)

        #Create the right Canvas and set the background color to white
        self.right_canvas = Canvas(image_frame, width=320, height=240, bg="white")
        self.right_canvas.pack(side="left", padx=10)

    def create_info_label(self):
        #Create a Label to display interactive information, set the background color to white, place it at the bottom and cover the entire width
        self.info_label = Label(self.root, text="This is information", font=("Arial", 12), bg="white", height=10)
        self.info_label.pack(side="bottom", fill="x")

    def start_capture(self):
        while True:
            ret, frame = self.camera.read()

            if not ret:
                print("Unable to read frame")
                break

            # Divide the screen into left and right halves
            height, width, _ = frame.shape
            left_half = frame[:, :width // 2]
            right_half = frame[:, width // 2:]

            # Use the PIL library to convert image data from OpenCV format to Tkinter PhotoImage format
            left_image = Image.fromarray(cv2.cvtColor(left_half, cv2.COLOR_BGR2RGB))
            right_image = Image.fromarray(cv2.cvtColor(right_half, cv2.COLOR_BGR2RGB))
            self.left_photo = ImageTk.PhotoImage(image=left_image)
            self.right_photo = ImageTk.PhotoImage(image=right_image)

            # Adjust the left and right image sizes to the size of the Canvas (320x240)
            left_resized = left_image.resize((320, 240), Image.ANTIALIAS)
            right_resized = right_image.resize((320, 240), Image.ANTIALIAS)

            self.left_photo_resized = ImageTk.PhotoImage(image=left_resized)
            self.right_photo_resized = ImageTk.PhotoImage(image=right_resized)

            # Display the resized left and right halves of the image on the Canvas
            self.left_canvas.create_image(0, 0, anchor="nw", image=self.left_photo_resized)
            self.right_canvas.create_image(0, 0, anchor="nw", image=self.right_photo_resized)

            self.root.update() # Update Tkinter window

    def take_snapshot(self):
        # Get the current left and right half images
        left_image = Image.fromarray(cv2.cvtColor(self.camera.read()[1], cv2.COLOR_BGR2RGB))
        right_image = Image.fromarray(cv2.cvtColor(self.camera.read()[1], cv2.COLOR_BGR2RGB))

        # Increment file name number
        self.snapshot_count + = 1

        # Save the left and right half images as PNG files
        left_filename = f"left{<!-- -->self.snapshot_count}.png"
        right_filename = f"right{<!-- -->self.snapshot_count}.png"

        left_image.save(left_filename, "png")
        right_image.save(right_filename, "png")

        # Update information label
        self.info_label.config(text=f"Left: {<!-- -->left_filename}, Right: {<!-- -->right_filename} have been saved!!")

def main():
    root = tk.Tk()
    my_window = MyWindow(root)
    root.mainloop()

if __name__ == "__main__":
    main()