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.
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!
You should read it
- What is Python? Why choose Python?
- 5 choose the best Python IDE for you
- Object-oriented programming in Python
- How to Start Programming in Python
- Multiple choice quiz about Python - Part 3
- Multiple choice quiz about Python - Part 1
- Multiple choice test on Python - Part 11
- Programming blockchain part 3: Python programming language
May be interested
- Multiple choice quiz about Python - Part 3today's topic quantrimang wants to challenge you is about file and exception handling in python. let's try the following 15 questions!
- 5 choose the best Python IDE for youin order to learn well python, it is essential that you find yourself an appropriate ide to develop. quantrimang would like to introduce some of the best environments to help improve your productivity.
- What is Python? Why choose Python?python is a powerful, high-level, object-oriented programming language, created by guido van rossum. python is easy to learn and emerging as one of the best introductory programming languages for people who are first exposed to programming languages.
- Module time in Pythonpython has a time module used to handle time-related tasks. tipsmake.com will work with you to find out the details and functions related to the time specified in this module. let's follow it!
- Python data type: string, number, list, tuple, set and dictionaryin this section, you'll learn how to use python as a computer, grasp python's data types and take the first step towards python programming.
- How to install Python on Windows, macOS, Linuxto get started with python, you first need to install python on the computer you are using, be it windows, macos or linux. below is a guide to installing python on your computer, specific to each operating system.
- How to set up Python to program on WSLget started with cross-platform python programming by setting up python on the windows subsystem for linux. here's how to set up python for wsl programming.
- Multiple choice quiz about Python - Part 4continue python's thematic quiz, part 4 goes back to the topic core data type - standard data types in python. let's try with quantrimang to try the 10 questions below.
- How to use Closure in Pythonin this article, tipsmake.com will work with you to learn about closure in python, how to define a closure and why you should use it. let's go find the answer!
- Functions in Pythonwhat is python function? how is the syntax, components, and function types in python? how to create functions in python? these questions will be answered in the python lesson below.