Suivez ce projet complet pour en savoir plus sur Python et le traitement d'images.
Que vous souhaitiez travailler sur un projet Python attrayant ou explorer différentes facettes de la programmation Python, la création d'une application de caméra répond à cet objectif. Cela implique de combiner différents aspects de la programmation Python, tels que le développement d'une interface utilisateur graphique (GUI), le traitement d'images et de vidéos et le multithreading.
De plus, résoudre des défis pratiques comme celui-ci vous aide à perfectionner vos compétences en résolution de problèmes. Ces compétences sont précieuses dans tout projet de programmation.
Configuration de votre environnement
Commence par créer un nouvel environnement virtuel. Cela isolera votre projet et garantira qu'il n'y a pas de conflit entre les différentes versions des packages que vous installez. Ensuite, exécutez cette commande de terminal :
pip install opencv-python pillow
Cette commande installera le OuvrirCV bibliothèque et
PIL (Python Imaging Library) dans votre environnement virtuel. Vous utiliserez OpenCV pour la fonctionnalité de vision par ordinateur et PIL pour la manipulation d'images.Le code source complet de ce projet est disponible dans un Dépôt GitHub.
Importer les bibliothèques requises
Une fois que vous avez installé ces bibliothèques, vous pouvez les importer avec d'autres modules nécessaires à partir de la bibliothèque standard de Python :
import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time
Vous allez utiliser tkinter créer une interface utilisateur graphique pour votre application et les modules os, threading et time pour leurs fonctionnalités associées. En séparant une partie de votre code en threads, vous lui permettre de s'exécuter simultanément.
Création d'un répertoire de galerie et définition de variables et d'indicateurs globaux
Créez un répertoire pour stocker les images capturées et les vidéos enregistrées. Cette étape garantira que le répertoire existe avant de procéder à la capture ou à l'enregistrement de vidéos.
ifnot os.path.exists("gallery"):
os.makedirs("gallery")
Définissez ensuite image_thumbnails et vignettes vidéo variables. Ceux-ci stockeront des vignettes d’images et de vidéos dans la galerie.
# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True
Le mise à jour_camera le drapeau contrôlera les mises à jour du flux de la caméra.
Capturer des images à partir du flux de la caméra
Définissez une fonction qui utilisera OpenCV pour capturer une image à partir du flux de la caméra. Il doit alors récupérer une image de la caméra, la sauvegarder dans le Galerie répertoire et affichez-le en utilisant show_image.
defcapture_image():
ret, frame = cap.read()
if ret:
# Generate a unique filename with a 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)
Démarrage et arrêt de l'enregistrement vidéo
Avant d'afficher une vidéo, vous avez besoin d'un moyen de la créer. Pour y parvenir, créez une fonction qui lance le processus d'enregistrement vidéo lorsque l'utilisateur souhaite capturer une vidéo. La fonction devrait également désactiver le Enregistrer (pour empêcher plusieurs enregistrements simultanément) et activez le Arrête d'enregistrer bouton. Cela indique que l'enregistrement est en cours.
defstart_recording():
global video_writer, recording_start_time, recording_stopped, update_cameraifnot video_writer:
timestamp = time.strftime("%Y%m%d%H%M%S")
video_path = os.path.join("gallery", f"recorded_video_{timestamp}.mp4")# Use mp4v codec (or try other codecs)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')# Adjust frame rate and resolution if needed
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)
# Start a separate thread for recording and time-lapse display
recording_thread = threading.Thread(target=record_and_display)
recording_thread.start()
Ensuite, créez une fonction qui arrête l'enregistrement vidéo et libère le graveur vidéo.
defstop_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)
Cette fonction met également à jour l'interface utilisateur permettant au Enregistrer et en désactivant le Arrête d'enregistrer bouton. Cela indique que l'enregistrement s'est arrêté.
Enregistrement et affichage de vidéos
Créez une fonction qui capturera en continu les images de la caméra, les traitera et les affichera sur l'interface graphique en tant que flux de la caméra. Il devrait le faire à moins que le Arrête d'enregistrer le bouton est enfoncé.
defrecord_and_display():
global recording_stopped, update_camerawhile video_writer andnot recording_stopped:
ret, frame = cap.read()if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# Calculate elapsed time and add it to the frame
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 = photovideo_writer.write(frame)
time.sleep(0.05)
camera_feed.after(10, update_camera_feed)
La fonction calcule également le temps écoulé depuis le début de l'enregistrement et l'affiche sur l'image vidéo.
Affichage des images et des vidéos capturées
Maintenant que vous avez capturé les images et enregistré les vidéos, vous avez besoin d'un moyen de les afficher.
Pour afficher les images, créez une fonction qui ouvre une image et l'affiche dans le flux de la caméra. Ceci est réalisé en ouvrant l'image à l'aide du PIL, puis en le convertissant dans un format qui tkinter peut afficher, et enfin mettre à jour le widget de flux de la caméra avec la nouvelle image.
defshow_image(image_path):
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image=image)
camera_feed.config(image=photo)
camera_feed.image = photo
Pour afficher les vidéos capturées, créez une fonction qui ouvre une fenêtre de lecteur vidéo où l'utilisateur peut visualiser les vidéos enregistrées. Il suspend également les mises à jour du flux de la caméra pendant la lecture de la vidéo.
defplay_video(video_path):
defclose_video_player():
video_player.destroy()
global update_camera
update_camera = Trueglobal update_camera
update_camera = Falsevideo_player = tk.Toplevel(root)
video_player.title("Video Player")video_cap = cv2.VideoCapture(video_path)
defupdate_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# Get the actual frame rate of the 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)
La suspension des mises à jour du flux de la caméra garantit une expérience visuelle fluide.
Création d'une vignette vidéo et ouverture de la galerie
Créez une fonction qui générera une image miniature pour une vidéo donnée. Cela permettra aux utilisateurs d’identifier plus facilement la vidéo qui les intéresse.
defcreate_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)
returnNone, None
Ensuite, créez une fonction qui lit une vidéo lorsqu'un utilisateur clique sur la vignette de la vidéo dans la fenêtre de la galerie :
defplay_video_from_thumbnail(video_path):
play_video(video_path)
Créez ensuite une fonction qui crée une nouvelle fenêtre dans laquelle l'utilisateur peut visualiser les images et vidéos capturées.
defopen_gallery():
global update_camera
update_camera = Falsegallery_window = tk.Toplevel(root)
gallery_window.title("Gallery")defback_to_camera():
gallery_window.destroy()
global update_camera# Resume updating the camera feed
update_camera = Trueback_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")]# Clear the existing image_thumbnails and video_thumbnails lists
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)defshow_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_photothumbnail_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)# Display the image filename below the 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)# Create a video thumbnail and get the filename
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()
# Store the video thumbnail PhotoImage objects
video_thumbnails.append(thumbnail_photo)
# Display the video filename below the thumbnail
video_name_label = tk.Label(gallery_window, text=video_name)
video_name_label.pack()
Des miniatures sont créées pour les images et les vidéos. Cela signifie que vous pouvez cliquer dessus pour afficher l'image en taille réelle ou lire la vidéo.
Création de l'interface utilisateur principale de votre application
Commencez par créer le principal tkinter fenêtre de l'application, puis donnez-lui un titre.
root = tk.Tk()
root.title("Camera Application")
Initialisez ensuite les variables requises.
video_writer = None
recording_start_time = 0# Initialize recording start time
recording_stopped = False# Initialize recording_stopped flag
Créez ensuite des boutons pour diverses 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)
Utilisez le gestionnaire de disposition de grille pour organiser les boutons dans la fenêtre principale.
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)
Créez un widget pour afficher le flux de la caméra et initialisez-le.
camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)
Ensuite, créez une fonction qui met à jour en permanence le flux de la caméra affiché dans le tkinter fenêtre.
defupdate_camera_feed():
if update_camera:
ifnot 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 = photoroot.after(10, update_camera_feed)
update_camera_feed()
Enfin, démarrez le principal tkinter boucle d'événements.
root.mainloop()
Cette boucle est responsable de la gestion des interactions des utilisateurs.
Test des fonctionnalités de l'application
Cette vidéo présente diverses fonctionnalités de l'application :
Aiguisez vos compétences Python avec OpenCV
OpenCV domine en matière de vision par ordinateur. Il fonctionne avec de nombreuses bibliothèques différentes, vous permettant de créer de nombreux projets sympas. Vous pouvez l'utiliser avec Python pour pratiquer et perfectionner vos compétences en programmation.