Sledite temu obsežnemu projektu, če želite izvedeti več o Pythonu in obdelavi slik.

Ne glede na to, ali želite delati na privlačnem projektu Python ali raziskati različne vidike programiranja Python, izdelava aplikacije kamere služi temu namenu. Vključuje združevanje različnih vidikov programiranja Python, kot je razvoj grafičnega uporabniškega vmesnika (GUI), obdelava slik in videa ter večnitnost.

Poleg tega reševanje praktičnih izzivov, kot je ta, pomaga izostriti vaše sposobnosti reševanja problemov. Te veščine so dragocene pri vsakem programskem podvigu.

Nastavitev vašega okolja

Začni z ustvarjanje novega virtualnega okolja. To bo izoliralo vaš projekt in zagotovilo, da ni konfliktov med različnimi različicami paketov, ki jih namestite. Nato zaženite ta terminalski ukaz:

pip install opencv-python pillow

Ta ukaz bo namestil OpenCV knjižnica in PIL (Python Imaging Library) v vašem virtualnem okolju. Uporabili boste OpenCV za funkcionalnost računalniškega vida in PIL za obdelavo slik.

Celotna izvorna koda tega projekta je na voljo v a Repozitorij GitHub.

instagram viewer

Uvažanje zahtevanih knjižnic

Ko namestite te knjižnice, jih lahko uvozite skupaj z drugimi potrebnimi moduli iz standardne knjižnice Python:

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

Boste uporaba tkinter ustvariti grafični uporabniški vmesnik za vašo aplikacijo ter module OS, Threading in Time za njihovo povezano funkcionalnost. Če del svoje kode razdelite na niti, boste omogočite sočasno izvajanje.

Ustvarjanje imenika galerije in definiranje globalnih spremenljivk in zastavic

Ustvarite imenik za shranjevanje zajetih slik in posnetih videoposnetkov. Ta korak bo zagotovil, da imenik obstaja, preden nadaljujete z zajemanjem ali snemanjem videoposnetkov.

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

Nato definirajte image_thumbnails in video_sličice spremenljivke. Ti bodo shranili sličice slik in videoposnetkov v galerijo.

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

The posodobitev_kamere zastavica bo nadzorovala posodobitve virov kamere.

Zajemanje slik iz vira kamere

Določite funkcijo, ki bo uporabljala OpenCV za zajem slike iz vira kamere. Nato bi moral pridobiti okvir iz fotoaparata in ga shraniti v galerija in ga prikažite z uporabo 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)

Zagon in zaustavitev snemanja videa

Preden prikažete video, potrebujete način, kako ga ustvariti. Če želite to doseči, ustvarite funkcijo, ki sproži postopek snemanja videa, ko uporabnik želi zajeti video. Funkcija mora tudi onemogočiti Zapis gumb (da preprečite več snemanj hkrati) in omogočite Ustavi snemanje gumb. To pomeni, da snemanje poteka.

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

Nato ustvarite funkcijo, ki ustavi snemanje videa in sprosti zapisovalnik 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)

Ta funkcija tudi posodobi uporabniški vmesnik, ki omogoča Zapis gumb in onemogočanje Ustavi snemanje gumb. To pomeni, da se je snemanje ustavilo.

Snemanje in prikaz videoposnetkov

Ustvarite funkcijo, ki bo nenehno zajemala okvirje iz kamere, jih obdelovala in prikazovala v GUI kot vir kamere. To bi moralo storiti, razen če Ustavi snemanje je pritisnjen gumb.

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)

Funkcija izračuna tudi pretečeni čas od začetka snemanja in ga prikaže na video okvirju.

Prikaz zajetih slik in videoposnetkov

Zdaj, ko ste posneli slike in videoposnetke, potrebujete način za njihov prikaz.

Za prikaz slik ustvarite funkcijo, ki odpre sliko in jo prikaže v viru kamere. To dosežete tako, da sliko odprete z PIL, nato ga pretvorite v obliko, ki tkinter lahko prikaže in končno posodobitev pripomočka za vir kamere z novo sliko.

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

Za prikaz zajetih videoposnetkov ustvarite funkcijo, ki odpre okno predvajalnika videoposnetkov, kjer si lahko uporabnik ogleda posnete videoposnetke. Prav tako začasno ustavi posodobitve virov kamere med predvajanjem videa.

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)

Zaustavitev posodobitev virov kamere zagotavlja nemoteno izkušnjo gledanja.

Ustvarjanje sličice videa in odpiranje galerije

Ustvarite funkcijo, ki bo ustvarila sličico za določen video. Tako bodo uporabniki lažje prepoznali video, ki jih zanima.

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

Nato ustvarite funkcijo, ki predvaja videoposnetek, ko uporabnik klikne sličico videoposnetka v oknu galerije:

defplay_video_from_thumbnail(video_path):
play_video(video_path)

Nato ustvarite funkcijo, ki ustvari novo okno, v katerem si lahko uporabnik ogleda zajete slike in videe.

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

Sličice so ustvarjene za slike in videoposnetke. To pomeni, da jih lahko kliknete za ogled slike v polni velikosti ali predvajanje videoposnetka.

Ustvarjanje glavnega uporabniškega vmesnika za vašo aplikacijo

Začnite z ustvarjanjem glavnega tkinter okno aplikacije in mu nato dajte naslov.

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

Nato inicializirajte zahtevane spremenljivke.

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

Nato ustvarite gumbe za različna dejanja.

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)

Za organiziranje gumbov v glavnem oknu uporabite upravitelja postavitve mreže.

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)

Ustvarite pripomoček za prikaz vira kamere in ga inicializirajte.

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

Nato ustvarite funkcijo, ki nenehno posodablja vir kamere, prikazan 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()

Končno zaženite glavno tkinter zanka dogodkov.

root.mainloop()

Ta zanka je odgovorna za obdelavo uporabniških interakcij.

Preizkušanje funkcij aplikacije

Ta video prikazuje različne funkcije aplikacije:

Izostrite svoje znanje Pythona z OpenCV

OpenCV prevladuje, ko gre za računalniški vid. Deluje z veliko različnimi knjižnicami, kar vam omogoča ustvarjanje številnih kul projektov. Uporabljate ga lahko s Pythonom za vadbo in izostritev svojih veščin programiranja.