Urmați acest proiect cuprinzător pentru a afla mai multe despre Python și procesarea imaginilor.
Indiferent dacă doriți să lucrați la un proiect Python captivant sau să explorați diverse fațete ale programării Python, construirea unei aplicații pentru cameră servește acestui scop. Acesta implică combinarea diferitelor aspecte ale programării Python, cum ar fi dezvoltarea interfeței grafice cu utilizatorul (GUI), procesarea imaginilor și video și multi-threading.
De asemenea, rezolvarea unor provocări practice ca aceasta vă ajută să vă ascuți abilitățile de rezolvare a problemelor. Aceste abilități sunt valoroase în orice efort de programare.
Configurarea mediului
Începe prin crearea unui nou mediu virtual. Acest lucru vă va izola proiectul și va asigura că nu există niciun conflict între diferitele versiuni ale pachetelor pe care le instalați. Apoi, rulați această comandă de terminal:
pip install opencv-python pillow
Această comandă va instala OpenCV bibliotecă și PIL (Python Imaging Library) în mediul dumneavoastră virtual. Veți folosi OpenCV pentru funcționalitatea de viziune pe computer și PIL pentru manipularea imaginilor.
Codul sursă complet al acestui proiect este disponibil în a Depozitul GitHub.
Importarea bibliotecilor necesare
După ce ați instalat aceste biblioteci, le puteți importa împreună cu alte module necesare din biblioteca standard Python:
import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time
vei utilizare tkinter pentru a crea o interfață grafică cu utilizatorul pentru aplicația dvs. și modulele OS, threading și time pentru funcționalitatea asociată acestora. Separând o parte din codul dvs. în fire, veți permiteți-l să ruleze concomitent.
Crearea unui director de galerie și definirea variabilelor și steagurilor globale
Creați un director pentru a stoca imaginile capturate și videoclipurile înregistrate. Acest pas va asigura că directorul există înainte de a continua să capturați sau să înregistrați videoclipuri.
ifnot os.path.exists("gallery"):
os.makedirs("gallery")
Apoi definiți imagini_miniaturi și miniaturi video variabile. Acestea vor stoca miniaturi ale imaginilor și videoclipurilor în galerie.
# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True
The update_camera flag va controla actualizările fluxului camerei.
Capturarea imaginilor din fluxul camerei
Definiți o funcție care va folosi OpenCV pentru a captura o imagine din fluxul camerei. Apoi ar trebui să recupereze un cadru de pe cameră, să îl salveze în Galerie director și afișați-l folosind arata_imagine.
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)
Pornirea și oprirea înregistrării video
Înainte de a afișa un videoclip, aveți nevoie de o modalitate de a-l crea. Pentru a realiza acest lucru, creați o funcție care inițiază procesul de înregistrare video atunci când utilizatorul dorește să captureze un videoclip. Funcția ar trebui, de asemenea, să dezactiveze Record butonul (pentru a preveni mai multe înregistrări simultan) și activați Opriți înregistrarea buton. Aceasta indică faptul că înregistrarea este în curs.
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()
Apoi, creați o funcție care oprește înregistrarea video și eliberează scriitorul 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)
Această funcție actualizează, de asemenea, interfața de utilizare, permițând Record butonul și dezactivarea Opriți înregistrarea buton. Aceasta indică faptul că înregistrarea s-a oprit.
Înregistrarea și afișarea videoclipurilor
Creați o funcție care va capta în mod continuu cadre de pe cameră, le va procesa și le va afișa pe GUI ca feed al camerei. Ar trebui să facă acest lucru, cu excepția cazului în care Opriți înregistrarea butonul este apăsat.
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)
Funcția calculează și timpul scurs de la începutul înregistrării și îl afișează pe cadrul video.
Afișarea imaginilor și videoclipurilor capturate
Acum că ați capturat imaginile și ați înregistrat videoclipurile, aveți nevoie de o modalitate de a le afișa.
Pentru a afișa imaginile, creați o funcție care deschide o imagine și o afișează în fluxul camerei. Acest lucru se realizează prin deschiderea imaginii folosind PIL, apoi convertindu-l într-un format care tkinter poate afișa și, în sfârșit, actualizarea widget-ului de feed al camerei cu noua imagine.
defshow_image(image_path):
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image=image)
camera_feed.config(image=photo)
camera_feed.image = photo
Pentru a afișa videoclipurile capturate, creați o funcție care deschide o fereastră de player video unde utilizatorul poate vizualiza videoclipurile înregistrate. De asemenea, întrerupe actualizările fluxului camerei în timpul redării videoclipului.
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)
Întreruperea actualizărilor fluxului camerei asigură o experiență de vizionare fluidă.
Crearea unei miniaturi video și deschiderea galeriei
Creați o funcție care va genera o imagine în miniatură pentru un anumit videoclip. Acest lucru va face mai ușor pentru utilizatori să identifice videoclipul de interes.
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
Apoi, creați o funcție care redă un videoclip atunci când un utilizator face clic pe miniatura videoclipului din fereastra galeriei:
defplay_video_from_thumbnail(video_path):
play_video(video_path)
Apoi creați o funcție care creează o nouă fereastră în care utilizatorul poate vizualiza imaginile și videoclipurile capturate.
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()
Miniaturile sunt create atât pentru imagini, cât și pentru videoclipuri. Aceasta înseamnă că puteți face clic pe ele pentru a vizualiza imaginea la dimensiunea completă sau pentru a reda videoclipul.
Crearea interfeței cu utilizatorul principal pentru aplicația dvs
Începeți prin a crea principalul tkinter fereastra aplicației și apoi dați-i un titlu.
root = tk.Tk()
root.title("Camera Application")
Apoi inițializați variabilele necesare.
video_writer = None
recording_start_time = 0# Initialize recording start time
recording_stopped = False# Initialize recording_stopped flag
Apoi creați butoane pentru diferite acțiuni.
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)
Utilizați managerul de aspect al grilei pentru a organiza butoanele din fereastra principală.
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ți un widget pentru a afișa fluxul camerei și inițializați-l.
camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)
Apoi, creați o funcție care actualizează continuu fluxul camerei afișat în tkinter fereastră.
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()
În cele din urmă, începeți principalul tkinter bucla de eveniment.
root.mainloop()
Această buclă este responsabilă pentru gestionarea interacțiunilor utilizatorului.
Testarea caracteristicilor aplicației
Acest videoclip demonstrează diferite caracteristici ale aplicației:
Îmbunătățiți-vă abilitățile Python cu OpenCV
OpenCV domină când vine vorba de viziunea computerizată. Funcționează cu o mulțime de biblioteci diferite, permițându-vă să creați multe proiecte interesante. Îl puteți folosi cu Python pentru a vă exersa și a vă îmbunătăți abilitățile de programare.