Sledujte tento komplexní projekt a zjistěte více o Pythonu a zpracování obrázků.

Ať už chcete pracovat na poutavém projektu v Pythonu nebo prozkoumat různé aspekty programování v Pythonu, vytvoření aplikace pro fotoaparát poslouží tomuto účelu. Zahrnuje kombinaci různých aspektů programování v Pythonu, jako je vývoj grafického uživatelského rozhraní (GUI), zpracování obrázků a videa a vícevláknové zpracování.

Také řešení praktických výzev, jako je tato, pomáhá vylepšit vaše dovednosti při řešení problémů. Tyto dovednosti jsou cenné v jakémkoli programátorském úsilí.

Nastavení vašeho prostředí

Začněte tím vytvoření nového virtuálního prostředí. To izoluje váš projekt a zajistí, že nedojde ke konfliktu mezi různými verzemi balíčků, které nainstalujete. Poté spusťte tento příkaz terminálu:

pip install opencv-python pillow

Tento příkaz nainstaluje OpenCV knihovna a PIL (Python Imaging Library) ve vašem virtuálním prostředí. OpenCV budete používat pro funkci počítačového vidění a PIL pro manipulaci s obrázky.

instagram viewer

Úplný zdrojový kód tohoto projektu je k dispozici v a úložiště GitHub.

Import požadovaných knihoven

Jakmile tyto knihovny nainstalujete, můžete je importovat spolu s dalšími nezbytnými moduly ze standardní knihovny Pythonu:

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

Budete použití tkinter k vytvoření grafického uživatelského rozhraní pro vaši aplikaci a moduly operačního systému, vláken a času pro jejich související funkce. Rozdělením části kódu do vláken to uděláte umožnit jeho souběžný chod.

Vytvoření adresáře galerie a definování globálních proměnných a příznaků

Vytvořte adresář pro ukládání pořízených snímků a nahraných videí. Tento krok zajistí, že adresář existuje, než budete pokračovat v nahrávání nebo nahrávání videí.

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

Poté definujte image_thumbnails a video_thumbnails proměnné. Ty budou ukládat miniatury obrázků a videí do galerie.

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

The update_camera příznak bude ovládat aktualizace zdroje kamery.

Pořizování snímků z fotoaparátu

Definujte funkci, která bude používat OpenCV k zachycení obrazu z kamery. Poté by měl načíst snímek z fotoaparátu a uložit jej do galerie adresář a zobrazte jej pomocí zobrazit_obrázek.

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)

Spuštění a zastavení nahrávání videa

Před zobrazením videa potřebujete způsob, jak jej vytvořit. Chcete-li toho dosáhnout, vytvořte funkci, která spustí proces nahrávání videa, když chce uživatel zachytit video. Funkce by měla také deaktivovat Záznam (pro zamezení vícenásobného nahrávání současně) a aktivujte Zastavit nahrávání knoflík. To znamená, že probíhá nahrávání.

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

Poté vytvořte funkci, která zastaví nahrávání videa a uvolní zapisovač videa.

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)

Tato funkce také aktualizuje uživatelské rozhraní umožňující Záznam tlačítko a deaktivaci Zastavit nahrávání knoflík. To znamená, že nahrávání bylo zastaveno.

Nahrávání a zobrazování videí

Vytvořte funkci, která bude nepřetržitě zachycovat snímky z kamery, zpracovávat je a zobrazovat v grafickém uživatelském rozhraní jako zdroj z kamery. Mělo by tak učinit, pokud není Zastavit nahrávání je stisknuto tlačítko.

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)

Funkce také vypočítá dobu, která uplynula od začátku nahrávání, a zobrazí ji na snímku videa.

Zobrazení pořízených obrázků a videí

Nyní, když jste pořídili snímky a nahráli videa, potřebujete způsob, jak je zobrazit.

Chcete-li zobrazit obrázky, vytvořte funkci, která otevře obrázek a zobrazí jej ve zdroji fotoaparátu. Toho je dosaženo otevřením obrázku pomocí PIL, poté jej převést do formátu, který tkinter může zobrazit a nakonec aktualizovat widget fotoaparátu novým obrázkem.

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

Chcete-li zobrazit zaznamenaná videa, vytvořte funkci, která otevře okno přehrávače videa, kde si uživatel může prohlížet nahraná videa. Během přehrávání videa také pozastaví aktualizace zdroje z fotoaparátu.

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)

Pozastavení aktualizací fotoaparátu zajišťuje plynulý zážitek ze sledování.

Vytvoření miniatury videa a otevření galerie

Vytvořte funkci, která vygeneruje miniaturu pro dané video. To uživatelům usnadní identifikaci zajímavého videa.

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

Dále vytvořte funkci, která přehraje video, když uživatel klikne na miniaturu videa v okně galerie:

defplay_video_from_thumbnail(video_path):
play_video(video_path)

Poté vytvořte funkci, která vytvoří nové okno, kde si uživatel může prohlížet pořízené snímky a videa.

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

Miniatury se vytvářejí pro obrázky i videa. To znamená, že na ně můžete kliknout a zobrazit obrázek v plné velikosti nebo přehrát video.

Vytvoření hlavního uživatelského rozhraní pro vaši aplikaci

Začněte vytvořením hlavního tkinter okno aplikace a poté jej pojmenujte.

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

Poté inicializujte požadované proměnné.

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

Poté vytvořte tlačítka pro různé akce.

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)

Pomocí správce rozložení mřížky uspořádejte tlačítka v hlavním okně.

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)

Vytvořte widget pro zobrazení zdroje z fotoaparátu a jeho inicializaci.

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

Poté vytvořte funkci, která průběžně aktualizuje obraz z kamery zobrazený v tkinter okno.

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

Nakonec spusťte hlavní tkinter smyčka událostí.

root.mainloop()

Tato smyčka je zodpovědná za zpracování uživatelských interakcí.

Testování funkcí aplikace

Toto video ukazuje různé funkce aplikace:

Vylepšete své dovednosti Python pomocí OpenCV

OpenCV dominuje, pokud jde o počítačové vidění. Pracuje se spoustou různých knihoven, což vám umožňuje vytvářet mnoho skvělých projektů. Můžete jej použít s Pythonem k procvičení a vypilování vašich programovacích dovedností.