Følg dette omfattende projekt for at lære mere om Python og billedbehandling.

Uanset om du vil arbejde på et engagerende Python-projekt eller udforske forskellige facetter af Python-programmering, tjener opbygningen af ​​en kameraapplikation dette formål. Det involverer at kombinere forskellige aspekter af Python-programmering, såsom udvikling af grafisk brugergrænseflade (GUI), billed- og videobehandling og multi-threading.

Løsning af praktiske udfordringer som denne hjælper også med at skærpe dine problemløsningsevner. Disse færdigheder er værdifulde i enhver programmeringsindsats.

Opsætning af dit miljø

Start med skabe et nyt virtuelt miljø. Dette vil isolere dit projekt og sikre, at der ikke er nogen konflikt mellem forskellige versioner af de pakker, du installerer. Kør derefter denne terminalkommando:

pip install opencv-python pillow

Denne kommando vil installere OpenCV bibliotek og PIL (Python Imaging Library) i dit virtuelle miljø. Du vil bruge OpenCV til computervisionsfunktionalitet og PIL til billedmanipulation.

instagram viewer

Den fulde kildekode til dette projekt er tilgængelig i en GitHub-depot.

Import af de nødvendige biblioteker

Når du har installeret disse biblioteker, kan du importere dem sammen med andre nødvendige moduler fra Pythons standardbibliotek:

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

Du vil brug tkinter at skabe en grafisk brugerflade til din applikation og OS, threading og tidsmoduler for deres tilknyttede funktionalitet. Ved at adskille noget af din kode i tråde, vil du gør det muligt at køre samtidigt.

Oprettelse af et gallerikatalog og definition af globale variabler og flag

Opret en mappe til at gemme optagne billeder og optagede videoer. Dette trin sikrer, at biblioteket eksisterer, før du fortsætter med at optage eller optage videoer.

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

Definer derefter image_thumbnails og video_thumbnails variabler. Disse vil gemme thumbnails af billeder og videoer i galleriet.

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

Det update_camera flag vil kontrollere kamerafeedopdateringer.

Optagelse af billeder fra kamerafeedet

Definer en funktion, der bruger OpenCV til at tage et billede fra kamerafeedet. Den skulle så hente en ramme fra kameraet, gemme den i galleri mappe, og vis den ved hjælp af vis_billede.

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)

Start og stop af videooptagelse

Før du viser en video, har du brug for en måde at oprette den på. For at opnå dette skal du oprette en funktion, der starter videooptagelsesprocessen, når brugeren ønsker at optage en video. Funktionen skal også deaktivere Optage knappen (for at forhindre flere optagelser samtidigt) og aktivere Stop optagelse knap. Dette indikerer, at optagelsen er i gang.

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

Opret derefter en funktion, der stopper videooptagelsen og frigiver videoskriveren.

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)

Denne funktion opdaterer også brugergrænsefladen, der aktiverer Optage knappen og deaktivering af Stop optagelse knap. Dette indikerer, at optagelsen er stoppet.

Optagelse og visning af videoer

Opret en funktion, der kontinuerligt optager billeder fra kameraet, behandler dem og viser dem på GUI'en som kamerafeed. Det bør den gøre, medmindre Stop optagelse knappen trykkes ned.

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)

Funktionen beregner også den forløbne tid siden optagelsen startede og viser den på videorammen.

Visning af optagne billeder og videoer

Nu hvor du har taget billederne og optaget videoerne, har du brug for en måde at vise dem på.

For at vise billederne skal du oprette en funktion, der åbner et billede og viser det i kamerafeedet. Dette opnås ved at åbne billedet ved hjælp af PIL, og derefter konvertere den til et format, der tkinter kan vise, og til sidst opdaterer kameraets feed-widget med det nye billede.

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

For at vise de optagne videoer skal du oprette en funktion, der åbner et videoafspillervindue, hvor brugeren kan se optagede videoer. Det sætter også kamerafeedopdateringer på pause, mens videoen afspilles.

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)

Pause kamerafeedopdateringer sikrer en jævn seeroplevelse.

Oprettelse af videominiaturebillede og åbning af galleriet

Opret en funktion, der genererer et miniaturebillede for en given video. Dette vil gøre det nemmere for brugerne at identificere videoen af ​​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

Opret derefter en funktion, der afspiller en video, når en bruger klikker på miniaturebilledet af videoen i gallerivinduet:

defplay_video_from_thumbnail(video_path):
play_video(video_path)

Opret derefter en funktion, der opretter et nyt vindue, hvor brugeren kan se de optagne billeder og videoer.

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

Der oprettes miniaturebilleder til både billeder og videoer. Det betyder, at du kan klikke på dem for at se billedet i fuld størrelse eller afspille videoen.

Oprettelse af hovedbrugergrænsefladen til din applikation

Start med at oprette den vigtigste tkinter programvinduet og derefter give det en titel.

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

Initialiser derefter de nødvendige variabler.

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

Opret derefter knapper til forskellige handlinger.

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)

Brug gitterlayouthåndtering til at organisere knapperne i hovedvinduet.

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)

Opret en widget for at vise kamerafeedet og initialisere det.

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

Opret derefter en funktion, der løbende opdaterer kamerafeedet, der vises i tkinter vindue.

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

Til sidst skal du starte det vigtigste tkinter begivenhedsløkke.

root.mainloop()

Denne sløjfe er ansvarlig for at håndtere brugerinteraktioner.

Test af appens funktioner

Denne video demonstrerer forskellige funktioner i appen:

Skærp dine Python-færdigheder med OpenCV

OpenCV dominerer, når det kommer til computervision. Det fungerer med en masse forskellige biblioteker, så du kan skabe mange fede projekter. Du kan bruge det med Python til at øve og skærpe dine programmeringsevner.