Segui questo progetto completo per saperne di più su Python e sull'elaborazione delle immagini.

Sia che tu voglia lavorare su un progetto Python coinvolgente o esplorare vari aspetti della programmazione Python, creare un'applicazione per fotocamera serve a questo scopo. Implica la combinazione di diversi aspetti della programmazione Python, come lo sviluppo dell'interfaccia utente grafica (GUI), l'elaborazione di immagini e video e il multi-threading.

Inoltre, risolvere sfide pratiche come questa aiuta ad affinare le tue capacità di risoluzione dei problemi. Queste competenze sono preziose in qualsiasi attività di programmazione.

Configurazione dell'ambiente

A partire da creando un nuovo ambiente virtuale. Ciò isolerà il tuo progetto e garantirà che non vi siano conflitti tra le diverse versioni dei pacchetti installati. Quindi, esegui questo comando da terminale:

pip install opencv-python pillow

Questo comando installerà il OpenCV biblioteca e PIL (Python Imaging Library) nel tuo ambiente virtuale. Utilizzerai OpenCV per la funzionalità di visione artificiale e PIL per la manipolazione delle immagini.

instagram viewer

Il codice sorgente completo di questo progetto è disponibile in a Repositorio GitHub.

Importazione delle librerie richieste

Una volta installate queste librerie, puoi importarle insieme ad altri moduli necessari dalla libreria standard di Python:

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

Lo farai utilizzo tkinter per creare un'interfaccia utente grafica per la tua applicazione e i moduli del sistema operativo, del threading e del tempo per le funzionalità associate. Separando parte del tuo codice in thread, lo farai consentirne l'esecuzione simultanea.

Creazione di una directory di gallerie e definizione di variabili e flag globali

Creare una directory per archiviare le immagini catturate e i video registrati. Questo passaggio garantirà che la directory esista prima di procedere con l'acquisizione o la registrazione dei video.

ifnot os.path.exists("gallery"):
os.makedirs("gallery")

Quindi definire image_thumbnails E video_miniature variabili. Questi memorizzeranno le miniature di immagini e video nella galleria.

# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True

IL aggiornamento_camera flag controllerà gli aggiornamenti del feed della telecamera.

Catturare immagini dal feed della fotocamera

Definire una funzione che utilizzerà OpenCV per acquisire un'immagine dal feed della fotocamera. Dovrebbe quindi recuperare un fotogramma dalla fotocamera, salvarlo nel file galleria directory e visualizzarla utilizzando mostra_immagine.

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)

Avvio e interruzione della registrazione video

Prima di visualizzare un video, è necessario un modo per crearlo. Per raggiungere questo obiettivo, crea una funzione che avvii il processo di registrazione video quando l'utente desidera catturare un video. La funzione dovrebbe anche disabilitare il file Documentazione (per evitare più registrazioni contemporaneamente) e abilitare il Interrompi la registrazione pulsante. Ciò indica che la registrazione è in corso.

defstart_recording():
global video_writer, recording_start_time, recording_stopped, update_camera

ifnot 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()

Quindi, crea una funzione che interrompa la registrazione del video e rilasci il masterizzatore video.

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)

Questa funzione aggiorna anche l'interfaccia utente abilitando il Documentazione pulsante e disabilitando il Interrompi la registrazione pulsante. Ciò indica che la registrazione è stata interrotta.

Registrazione e visualizzazione di video

Crea una funzione che catturerà continuamente i fotogrammi dalla fotocamera, li elaborerà e li visualizzerà sulla GUI come feed della fotocamera. Dovrebbe farlo a meno che il Interrompi la registrazione viene premuto il pulsante.

defrecord_and_display():
global recording_stopped, update_camera

while 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 = photo

video_writer.write(frame)
time.sleep(0.05)

camera_feed.after(10, update_camera_feed)

La funzione calcola anche il tempo trascorso dall'inizio della registrazione e lo visualizza sul fotogramma video.

Visualizzazione di immagini e video catturati

Ora che hai catturato le immagini e registrato i video, hai bisogno di un modo per visualizzarli.

Per visualizzare le immagini, creare una funzione che apra un'immagine e la visualizzi nel feed della fotocamera. Ciò si ottiene aprendo l'immagine utilizzando il file PIL, quindi convertendolo in un formato tale tkinter può visualizzare e infine aggiornare il widget del feed della fotocamera con la nuova immagine.

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

Per visualizzare i video catturati, creare una funzione che apra una finestra del lettore video in cui l'utente può visualizzare i video registrati. Inoltre, mette in pausa gli aggiornamenti del feed della fotocamera durante la riproduzione del video.

defplay_video(video_path):
defclose_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)

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 sospensione degli aggiornamenti dei feed della fotocamera garantisce un'esperienza visiva fluida.

Creazione della miniatura del video e apertura della Galleria

Crea una funzione che genererà un'immagine in miniatura per un determinato video. Ciò renderà più semplice per gli utenti identificare il video di interesse.

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

Successivamente, crea una funzione che riproduca un video quando un utente fa clic sulla miniatura del video nella finestra della galleria:

defplay_video_from_thumbnail(video_path):
play_video(video_path)

Quindi crea una funzione che crei una nuova finestra in cui l'utente può visualizzare le immagini e i video catturati.

defopen_gallery():
global update_camera
update_camera = False

gallery_window = tk.Toplevel(root)
gallery_window.title("Gallery")

defback_to_camera():
gallery_window.destroy()
global update_camera

# Resume updating the 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")]

# 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_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)

# 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()

Le miniature vengono create sia per le immagini che per i video. Ciò significa che puoi fare clic su di essi per visualizzare l'immagine a dimensione intera o riprodurre il video.

Creazione dell'interfaccia utente principale per la tua applicazione

Inizia creando il main tkinter finestra dell'applicazione e quindi assegnargli un titolo.

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

Quindi inizializzare le variabili richieste.

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

Quindi crea pulsanti per varie azioni.

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)

Utilizzare il gestore del layout della griglia per organizzare i pulsanti nella finestra 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)

Crea un widget per visualizzare il feed della telecamera e inizializzalo.

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

Quindi, crea una funzione che aggiorni continuamente il feed della fotocamera visualizzato nel file tkinter finestra.

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 = photo

root.after(10, update_camera_feed)

update_camera_feed()

Infine, avvia il main tkinter ciclo di eventi.

root.mainloop()

Questo ciclo è responsabile della gestione delle interazioni dell'utente.

Testare le funzionalità dell'app

Questo video mostra varie funzionalità dell'app:

Affinare le tue abilità Python con OpenCV

OpenCV domina quando si tratta di visione artificiale. Funziona con molte librerie diverse che ti consentono di creare molti progetti interessanti. Puoi usarlo con Python per esercitarti e affinare le tue capacità di programmazione.