How to build a Camera app with Python

You want to learn more about Python and image processing. The guide below will show you how to build a camera app using Python.

You want to learn more about Python and image processing. The guide below will show you how to build a camera app using Python.

How to build a Camera app with Python Picture 1How to build a Camera app with Python Picture 1

Whether you want to work on a cool Python project or explore different aspects of Python programming, building a camera app is a great way to achieve that goal. It involves combining different aspects of Python programming, such as GUI development, image & video processing, and multithreading.

In addition, solving real-life challenges like this also helps you improve your problem-solving skills, which is extremely valuable when you want to become a good programmer.

Set up the environment

Start by creating a new virtual environment. That will isolate the project and ensure there are no conflicts between versions of installed packages. Then, run this terminal command:

pip install opencv-python pillow

The above command will install OpenCV and PIL libraries in the virtual environment. You will use OpenCV for computer vision and PIL for image processing.

Import the necessary libraries

Once you have installed these libraries, you can import them along with other necessary modules from the Python standard library:

import tkinter as tk import cv2 from PIL import Image, ImageTk import os import threading import time

You will use tkinter to create a GUI for the application and the operating system, thread, and timing modules for their associated functionality. By separating some code into threads, you can have that code run concurrently.

Create photo gallery categories and define global variables & flags

Create a folder containing captured photos and recorded videos. This step ensures that folder exists before recording the video.

if not os.path.exists("gallery"): os.makedirs("gallery")

Then define the image_thumbnails and video_thumbnails variables . They will contain images that represent the videos and photos in the gallery.

#Tạo image_thumbnails là một danh sách toàn cục image_thumbnails = [] video_thumbnails = [] # Danh sách mới cho ảnh đại diện video update_camera = True

The update_camera flag will control camera table updates.

Take photos from the camera feed

Define a function that will use OpenCV to capture images from the camera feed. It then retrieves a frame from the camera, saves it in the gallery folder , and displays it using show_image .

def capture_image(): ret, frame = cap.read() if ret: # Tạo filename riêng với timestamp timestamp = time.strftime("%Y%m%d%H%M%S") image_path = os.path.join("gallery", f"captured_image_{timestamp}.jpg") cv2.imwrite(image_path, frame) show_image(image_path)

Start and stop video recording

Before displaying a video, you need to create it. To achieve this, create a function that starts recording video when the user wants it. This function also disables the Record button and enables the Stop Recording button . This action indicates that recording is in progress.

def start_recording(): global video_writer, recording_start_time, recording_stopped, update_camera if not video_writer: timestamp = time.strftime("%Y%m%d%H%M%S") video_path = os.path.join("gallery", f"recorded_video_{timestamp}.mp4") # Dùng codec mp4v (hoặc thử codecs khác) fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Điều chỉnh tốc độ khung hình và độ phân giải nếu cần video_writer = cv2.VideoWriter(video_path, fourcc, 20.0, (640, 480)) recording_start_time = time.time() recording_stopped = False record_button.config(state=tk.DISABLED) stop_button.config(state=tk.NORMAL) # Bắt đầu luồng riêng cho ghi và hiện thời gian trôi qua recording_thread = threading.Thread(target=record_and_display) recording_thread.start()

Then create a function that stops recording and plays the video.

def stop_recording(): global video_writer, recording_stopped if video_writer: video_writer.release() recording_stopped = True record_button.config(state=tk.NORMAL) stop_button.config(state=tk.DISABLED)

This function also updates the UI and enables the Record button and disables the Stop Record button . This indicates that recording has stopped.

Record and display video

Create a function that will continuously record frames from the camera, process them, and display them on the GUI as a camera feed. It will do so unless you press the Stop Recording button .

def record_and_display(): global recording_stopped, update_camera while video_writer and not recording_stopped: ret, frame = cap.read() if ret: frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Tính thời gian trôi qua và thêm nó vào khung hình elapsed_time = time.time() - recording_start_time timestamp = f"Time Elapsed: {int(elapsed_time)}s" cv2.putText(frame, timestamp, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2) img = Image.fromarray(frame) photo = ImageTk.PhotoImage(image=img) camera_feed.config(image=photo) camera_feed.image = photo video_writer.write(frame) time.sleep(0.05) camera_feed.after(10, update_camera_feed) 

This function also calculates the time elapsed since the start of recording and displays it on the video frame.

Show recorded photos and videos

Now that you have your photos and recorded videos, you need a way to display them.

To display an image, create a function that opens an image and displays it in the camera feed. This is achieved by opening the image with PIL , then converting it to a format that tkinter can render, and finally updating the camera feed widget with this new image.

def show_image(image_path): image = Image.open(image_path) photo = ImageTk.PhotoImage(image=image) camera_feed.config(image=photo) camera_feed.image = photo

To show the recorded video, create a function that opens a video playback window where the user can view the recorded video. It also pauses camera feed updates while video is playing.

def play_video(video_path): def close_video_player(): video_player.destroy() global update_camera update_camera = True global update_camera update_camera = False video_player = tk.Toplevel(root) video_player.title("Video Player") video_cap = cv2.VideoCapture(video_path) def update_video_frame(): ret, frame = video_cap.read() if ret: frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = Image.fromarray(frame) photo = ImageTk.PhotoImage(image=img) video_label.config(image=photo) video_label.image = photo # Lấy tốc độ khung hình thực tế cho video frame_rate = video_cap.get(cv2.CAP_PROP_FPS) delay = int(1000 / frame_rate) video_player.after(delay, update_video_frame) else: video_player.destroy() video_label = tk.Label(video_player) video_label.pack() update_video_frame() video_player.protocol("WM_DELETE_WINDOW", close_video_player)

Pause camera feed updates to ensure a smooth viewing experience.

Create a video avatar and open the gallery

Create a function that will create a small thumbnail for the provided video. This makes it easier for users to identify the video they want to watch.

def create_video_thumbnail(video_path): video_cap = cv2.VideoCapture(video_path) ret, frame = video_cap.read() if ret: frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) thumbnail = Image.fromarray(frame).resize((100, 100)) thumbnail_photo = ImageTk.PhotoImage(image=thumbnail) return thumbnail_photo, os.path.basename(video_path) return None, None

Next, create a function that plays the video when the user clicks on the video's avatar in the gallery window:

def play_video_from_thumbnail(video_path): play_video(video_path)

Then create a function that opens a new window where users can view captured & recorded photos and videos.

def open_gallery(): global update_camera update_camera = False gallery_window = tk.Toplevel(root) gallery_window.title("Gallery") def back_to_camera(): gallery_window.destroy() global update_camera # Tiếp tục cập nhật camera feed update_camera = True back_button = tk.Button(gallery_window, text="Back to Camera", command=back_to_camera) back_button.pack() gallery_dir = "gallery" image_files = [f for f in os.listdir(gallery_dir) if f.endswith(".jpg")] video_files = [f for f in os.listdir(gallery_dir) if f.endswith(".mp4")] # Xóa danh sách image_thumbnails và video_thumbnails del image_thumbnails[:] del video_thumbnails[:] for image_file in image_files: image_path = os.path.join(gallery_dir, image_file) thumbnail = Image.open(image_path).resize((100, 100)) thumbnail_photo = ImageTk.PhotoImage(image=thumbnail) image_name = os.path.basename(image_file) def show_image_in_gallery(img_path, img_name): image_window = tk.Toplevel(gallery_window) image_window.title("Image") img = Image.open(img_path) img_photo = ImageTk.PhotoImage(img) img_label = tk.Label(image_window, image=img_photo) img_label.image = img_photo img_label.pack() img_label_name = tk.Label(image_window, text=img_name) img_label_name.pack() thumbnail_label = tk.Label(gallery_window, image=thumbnail_photo) thumbnail_label.image = thumbnail_photo thumbnail_label.bind("", lambda event, img_path=image_path, img_name=image_name: show_image_in_gallery(img_path, img_name)) thumbnail_label.pack() image_thumbnails.append(thumbnail_photo) # Hiện tên file ảnh bên dưới thumbnail image_name_label = tk.Label(gallery_window, text=image_name) image_name_label.pack() for video_file in video_files: video_path = os.path.join(gallery_dir, video_file) # Tạo thumbnail video và lấy tên file thumbnail_photo, video_name = create_video_thumbnail(video_path) if thumbnail_photo: video_thumbnail_button = tk.Button( gallery_window, image=thumbnail_photo, command=lambda path=video_path: play_video_from_thumbnail(path) ) video_thumbnail_button.pack() # Chứa các đối tượng PhotoImage là ảnh đại diện video video_thumbnails.append(thumbnail_photo) # Hiện tên file video bên dưới ảnh đại diện video_name_label = tk.Label(gallery_window, text=video_name) video_name_label.pack()

Thumbnails are created for both photos and videos. That means you can click on them to view full-size photos or play videos.

Create the main user interface for the application

Start by creating the main tkinter application window , then give it a name:

root = tk.Tk() root.title("Camera Application")

Then initialize the necessary variables.

video_writer = None recording_start_time = 0 # Initialize recording start time recording_stopped = False # Initialize recording_stopped flag

Next, create buttons for different actions.

capture_button = tk.Button(root, text="Capture", command=capture_image) record_button = tk.Button(root, text="Record", command=start_recording) stop_button = tk.Button(root, text="Stop Recording", command=stop_recording) gallery_button = tk.Button(root, text="Gallery", command=open_gallery) quit_button = tk.Button(root, text="Quit", command=root.quit)

Use the layout manager to arrange buttons in the main window.

capture_button.grid(row=0, column=0, padx=10, pady=10) record_button.grid(row=0, column=1, padx=10, pady=10) stop_button.grid(row=0, column=2, padx=10, pady=10) gallery_button.grid(row=0, column=3, padx=10, pady=10) quit_button.grid(row=0, column=4, padx=10, pady=10)

Create a widget to display the camera feed and initialize it.

camera_feed = tk.Label(root) camera_feed.grid(row=1, column=0, columnspan=5) cap = cv2.VideoCapture(0)

Next, create a function that continuously updates the camera feed displayed in the tkinter window .

def update_camera_feed(): if update_camera: if not video_writer: ret, frame = cap.read() if ret: frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = Image.fromarray(frame) photo = ImageTk.PhotoImage(image=img) camera_feed.config(image=photo) camera_feed.image = photo root.after(10, update_camera_feed) update_camera_feed()

Finally, start the main tkinter event loop .

root.mainloop()

This loop is responsible for handling user interactions.

Finally, you just need to take a test drive to check its features. It's done!

5 ★ | 2 Vote