Kövesse ezt az átfogó projektet, hogy többet tudjon meg a Pythonról és a képfeldolgozásról.
Akár egy lebilincselő Python-projekten szeretne dolgozni, akár a Python programozás különböző aspektusait szeretné felfedezni, egy kameraalkalmazás elkészítése ezt a célt szolgálja. Ez magában foglalja a Python programozás különböző aspektusainak kombinálását, mint például a grafikus felhasználói felület (GUI) fejlesztése, a kép- és videófeldolgozás, valamint a többszálú feldolgozás.
Ezenkívül az ehhez hasonló gyakorlati kihívások megoldása segít a problémamegoldó készségeinek fejlesztésében. Ezek a készségek értékesek minden programozási törekvésben.
Környezetének beállítása
Kezdje ezzel új virtuális környezet létrehozása. Ez elszigeteli a projektet, és biztosítja, hogy ne legyen ütközés a telepített csomagok különböző verziói között. Ezután futtassa ezt a terminálparancsot:
pip install opencv-python pillow
Ez a parancs telepíti a OpenCV könyvtár és PIL (Python Imaging Library) a virtuális környezetben. Az OpenCV-t a számítógépes látásfunkciókhoz, a PIL-t pedig a képkezeléshez használja.
A projekt teljes forráskódja elérhető a GitHub adattár.
A szükséges könyvtárak importálása
Miután telepítette ezeket a könyvtárakat, importálhatja őket a többi szükséges modullal együtt a Python szabványos könyvtárából:
import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time
fogsz használat tkinter grafikus felhasználói felület létrehozásához alkalmazásához, valamint az operációs rendszerhez, a szálfűzéshez és az időmodulokhoz a kapcsolódó funkciókhoz. Ha a kód egy részét szálakra választja, akkor lehetővé teszi egyidejű futtatását.
Galériakönyvtár létrehozása és globális változók és zászlók meghatározása
Hozzon létre egy könyvtárat a rögzített képek és rögzített videók tárolására. Ez a lépés biztosítja, hogy a könyvtár létezik-e, mielőtt folytatná a videók rögzítését vagy rögzítését.
ifnot os.path.exists("gallery"):
os.makedirs("gallery")
Ezután határozza meg image_thumbnails és video_thumbnails változók. Ezek a képek és videók miniatűrjeit tárolják a galériában.
# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True
A update_camera zászló fogja szabályozni a kamera hírfolyamának frissítéseit.
Képek rögzítése a kamera feedből
Határozzon meg egy funkciót, amely az OpenCV-t használja a kép rögzítésére a kamera feedből. Ezután le kell kérnie egy keretet a kamerából, és el kell mentenie a Képtár könyvtárat, és jelenítse meg a használatával 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)
Videofelvétel indítása és leállítása
Mielőtt megjelenítene egy videót, szüksége van egy módra a létrehozásához. Ennek eléréséhez hozzon létre egy funkciót, amely elindítja a videó rögzítési folyamatát, amikor a felhasználó videót szeretne rögzíteni. A funkciónak le kell tiltania a Rekord gombot (több felvétel egyidejű megakadályozásához), és engedélyezze a Felvétel leállítása gomb. Ez azt jelzi, hogy a felvétel folyamatban van.
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()
Ezután hozzon létre egy funkciót, amely leállítja a videofelvételt, és felszabadítja a videóírót.
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)
Ez a funkció frissíti a felhasználói felületet is, lehetővé téve a Rekord gombot és letiltja a Felvétel leállítása gomb. Ez azt jelzi, hogy a felvétel leállt.
Videók rögzítése és megjelenítése
Hozzon létre egy funkciót, amely folyamatosan rögzíti a képkockákat a kamerából, feldolgozza azokat, és megjeleníti a grafikus felhasználói felületen, mint a kamera feedje. Ezt meg kell tennie, kivéve ha a Felvétel leállítása gombot megnyomják.
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)
A funkció kiszámítja a felvétel kezdete óta eltelt időt is, és megjeleníti a videókockán.
Rögzített képek és videók megjelenítése
Most, hogy elkészítette a képeket és rögzítette a videókat, meg kell jelenítenie őket.
A képek megjelenítéséhez hozzon létre egy funkciót, amely megnyit egy képet, és megjeleníti azt a kamera hírfolyamában. Ez a kép megnyitásával érhető el a PIL, majd konvertálja olyan formátumba, amely tkinter képes megjeleníteni, és végül frissíteni a kamera feed widgetet az új képpel.
defshow_image(image_path):
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image=image)
camera_feed.config(image=photo)
camera_feed.image = photo
A rögzített videók megjelenítéséhez hozzon létre egy funkciót, amely megnyit egy videólejátszó ablakot, ahol a felhasználó megtekintheti a rögzített videókat. A videó lejátszása közben szünetelteti a kamera hírfolyamának frissítését is.
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)
A kamera feed-frissítéseinek szüneteltetése zökkenőmentes megtekintési élményt biztosít.
Videó miniatűr létrehozása és a galéria megnyitása
Hozzon létre egy függvényt, amely egy miniatűr képet generál egy adott videóhoz. Ez megkönnyíti a felhasználók számára az érdeklődési körnek megfelelő videó azonosítását.
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
Ezután hozzon létre egy funkciót, amely lejátssza a videót, amikor a felhasználó a videó miniatűrére kattint a galériaablakban:
defplay_video_from_thumbnail(video_path):
play_video(video_path)
Ezután hozzon létre egy funkciót, amely egy új ablakot hoz létre, ahol a felhasználó megtekintheti a rögzített képeket és videókat.
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()
A miniatűrök mind a képekhez, mind a videókhoz készülnek. Ez azt jelenti, hogy rájuk kattintva megtekintheti a teljes méretű képet vagy lejátszhatja a videót.
A fő felhasználói felület létrehozása az alkalmazáshoz
Kezdje a fő létrehozásával tkinter alkalmazás ablakát, majd adjon neki címet.
root = tk.Tk()
root.title("Camera Application")
Ezután inicializálja a szükséges változókat.
video_writer = None
recording_start_time = 0# Initialize recording start time
recording_stopped = False# Initialize recording_stopped flag
Ezután hozzon létre gombokat a különféle műveletekhez.
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)
A főablak gombjainak rendszerezéséhez használja a rácselrendezés-kezelőt.
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)
Hozzon létre egy widgetet a kamera hírfolyamának megjelenítéséhez, és inicializálja azt.
camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)
Ezután hozzon létre egy funkciót, amely folyamatosan frissíti a kamera hírfolyamát, amely a képernyőn jelenik meg tkinter ablak.
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()
Végül indítsa el a fő tkinter eseményhurok.
root.mainloop()
Ez a hurok felelős a felhasználói interakciók kezeléséért.
Az alkalmazás funkcióinak tesztelése
Ez a videó az alkalmazás különféle funkcióit mutatja be:
Élesítse Python-készségeit OpenCV-vel
Az OpenCV dominál a számítógépes látás terén. Számos különböző könyvtárral működik, így számos nagyszerű projektet hozhat létre. Használhatja a Pythonnal programozási készségeinek gyakorlására és élesítésére.