Śledź ten kompleksowy projekt, aby dowiedzieć się więcej o Pythonie i przetwarzaniu obrazów.
Niezależnie od tego, czy chcesz pracować nad angażującym projektem w języku Python, czy poznawać różne aspekty programowania w języku Python, tworzenie aplikacji aparatu służy temu celowi. Obejmuje łączenie różnych aspektów programowania w języku Python, takich jak tworzenie graficznego interfejsu użytkownika (GUI), przetwarzanie obrazów i wideo oraz wielowątkowość.
Ponadto rozwiązywanie praktycznych wyzwań, takich jak to, pomaga wyostrzyć umiejętności rozwiązywania problemów. Umiejętności te są cenne w każdym przedsięwzięciu programistycznym.
Konfigurowanie środowiska
Zacząć od tworzenie nowego środowiska wirtualnego. Spowoduje to odizolowanie projektu i zagwarantuje, że nie będzie konfliktu między różnymi wersjami instalowanych pakietów. Następnie uruchom to polecenie terminala:
pip install opencv-python pillow
To polecenie zainstaluje plik Otwórz CV biblioteka i PIL (Python Imaging Library) w środowisku wirtualnym. Będziesz używać OpenCV do funkcji widzenia komputerowego i PIL do manipulacji obrazem.
Pełny kod źródłowy tego projektu jest dostępny w formacie Repozytorium GitHuba.
Importowanie wymaganych bibliotek
Po zainstalowaniu tych bibliotek możesz je zaimportować wraz z innymi niezbędnymi modułami ze standardowej biblioteki Pythona:
import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time
Będziesz używać tkinter do stworzenia graficznego interfejsu użytkownika dla aplikacji oraz modułów systemu operacyjnego, wątków i czasu dla powiązanych z nimi funkcjonalności. Dzieląc część kodu na wątki, zrobisz to umożliwić mu jednoczesne działanie.
Tworzenie katalogu galerii i definiowanie zmiennych globalnych i flag
Utwórz katalog do przechowywania przechwyconych obrazów i nagranych filmów. Ten krok zapewni, że katalog istnieje przed przystąpieniem do przechwytywania lub nagrywania filmów.
ifnot os.path.exists("gallery"):
os.makedirs("gallery")
Następnie zdefiniuj miniatury_obrazu I miniatury wideo zmienne. Będą one przechowywać miniatury zdjęć i filmów w galerii.
# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True
The aktualizacja_kamery flaga będzie kontrolować aktualizacje transmisji z kamery.
Przechwytywanie obrazów z kanału kamery
Zdefiniuj funkcję, która będzie używać OpenCV do przechwytywania obrazu z obrazu z kamery. Powinien następnie pobrać klatkę z kamery i zapisać ją w formacie Galeria katalog i wyświetl go za pomocą pokaż_obraz.
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)
Uruchamianie i zatrzymywanie nagrywania wideo
Zanim wyświetlisz wideo, potrzebujesz sposobu na jego utworzenie. Aby to osiągnąć, utwórz funkcję inicjującą proces nagrywania wideo, gdy użytkownik chce przechwycić wideo. Funkcja powinna również wyłączyć Nagrywać przycisk (aby zapobiec wielokrotnemu nagrywaniu jednocześnie) i włącz opcję Zatrzymaj nagrywanie przycisk. Oznacza to, że trwa nagrywanie.
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()
Następnie utwórz funkcję, która zatrzyma nagrywanie wideo i zwolni moduł nagrywający wideo.
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 funkcja aktualizuje również interfejs użytkownika, umożliwiając Nagrywać przycisk i wyłączenie Zatrzymaj nagrywanie przycisk. Oznacza to, że nagrywanie zostało zatrzymane.
Nagrywanie i wyświetlanie filmów
Utwórz funkcję, która będzie stale przechwytywać klatki z kamery, przetwarzać je i wyświetlać w GUI jako obraz z kamery. Powinien to zrobić, chyba że Zatrzymaj nagrywanie przycisk jest wciśnięty.
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)
Funkcja oblicza również czas, jaki upłynął od rozpoczęcia nagrywania i wyświetla go na klatce wideo.
Wyświetlanie przechwyconych obrazów i filmów
Teraz, gdy już zrobiłeś zdjęcia i nagrałeś filmy, potrzebujesz sposobu na ich wyświetlenie.
Aby wyświetlić obrazy, utwórz funkcję, która otworzy obraz i wyświetli go w obrazie z kamery. Osiąga się to poprzez otwarcie obrazu za pomocą przycisku PIL, a następnie konwertując go do formatu, który tkinter można wyświetlić, i na koniec zaktualizować widżet obrazu z kamery o nowy obraz.
defshow_image(image_path):
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image=image)
camera_feed.config(image=photo)
camera_feed.image = photo
Aby wyświetlić przechwycone filmy, utwórz funkcję otwierającą okno odtwarzacza wideo, w którym użytkownik będzie mógł obejrzeć nagrane filmy. Wstrzymuje także aktualizacje kanałów kamery podczas odtwarzania wideo.
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)
Wstrzymywanie aktualizacji kanałów z kamery zapewnia płynne oglądanie.
Tworzenie miniatury wideo i otwieranie galerii
Utwórz funkcję, która wygeneruje miniaturę dla danego filmu. Ułatwi to użytkownikom identyfikację interesującego filmu.
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
Następnie utwórz funkcję odtwarzającą wideo, gdy użytkownik kliknie miniaturę filmu w oknie galerii:
defplay_video_from_thumbnail(video_path):
play_video(video_path)
Następnie utwórz funkcję, która utworzy nowe okno, w którym użytkownik będzie mógł przeglądać przechwycone obrazy i filmy.
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()
Miniatury są tworzone zarówno dla zdjęć, jak i filmów. Oznacza to, że możesz je kliknąć, aby wyświetlić obraz w pełnym rozmiarze lub odtworzyć wideo.
Tworzenie głównego interfejsu użytkownika dla Twojej aplikacji
Zacznij od utworzenia pliku głównego tkinter okno aplikacji, a następnie nadaj mu tytuł.
root = tk.Tk()
root.title("Camera Application")
Następnie zainicjuj wymagane zmienne.
video_writer = None
recording_start_time = 0# Initialize recording start time
recording_stopped = False# Initialize recording_stopped flag
Następnie utwórz przyciski do różnych akcji.
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)
Użyj menedżera układu siatki, aby uporządkować przyciski w oknie głównym.
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)
Utwórz widżet, aby wyświetlić obraz z kamery i go zainicjować.
camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)
Następnie utwórz funkcję, która na bieżąco aktualizuje obraz z kamery wyświetlany w pliku 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 = photoroot.after(10, update_camera_feed)
update_camera_feed()
Na koniec uruchom główny tkinter pętla zdarzeń.
root.mainloop()
Pętla ta odpowiada za obsługę interakcji użytkownika.
Testowanie funkcji aplikacji
Ten film przedstawia różne funkcje aplikacji:
Udoskonalaj swoje umiejętności w zakresie Pythona dzięki OpenCV
OpenCV dominuje, jeśli chodzi o wizję komputerową. Współpracuje z wieloma różnymi bibliotekami, umożliwiając tworzenie wielu fajnych projektów. Możesz go używać z Pythonem, aby ćwiczyć i doskonalić swoje umiejętności programowania.