Jak stworzyć aplikację kamery w Pythonie
Niezależnie od tego, czy chcesz pracować nad wciągającym projektem w Pythonie, czy też poznać różne aspekty programowania w Pythonie, tworzenie aplikacji kamery służy temu celowi. Wiąże się to z połączeniem różnych aspektów programowania w Pythonie, takich jak tworzenie graficznego interfejsu użytkownika (GUI), przetwarzanie obrazu i wideo oraz wielowątkowość. Ponadto, rozwiązywanie rzeczywistych problemów, takich jak ten, służy poprawie umiejętności krytycznego myślenia i rozwiązywania problemów. Takie umiejętności mają ogromne znaczenie w wielu projektach związanych z tworzeniem oprogramowania.
Konfiguracja środowiska
Na początek utwórz nowe środowisko wirtualne, które oddzieli projekt od potencjalnych rozbieżności wynikających z konfliktu wersji pakietów. Następnie wykonaj następujące polecenie w terminalu:
pip install opencv-python pillow
Niniejsze polecenie ułatwi instalację zarówno biblioteki OpenCV, która zapewnia kompleksowy zestaw narzędzi do wykonywania różnych zadań związanych z wizją komputerową, jak i Python Imaging Library (PIL), niezbędnego modułu, który umożliwia użytkownikom wykonywanie rozległych operacji przetwarzania obrazu. W związku z tym można wykorzystać OpenCV ze względu na solidny zestaw funkcji wizji komputerowej, jednocześnie wykorzystując PIL do skomplikowanej manipulacji obrazami w środowisku wirtualnym.
Dostęp do pełnego kodu źródłowego tego projektu można uzyskać za pośrednictwem repozytorium GitHub, które służy jako cyfrowa przestrzeń dyskowa dla programistów do udostępniania i współpracy nad ich pracą.
Importowanie wymaganych bibliotek
Po zainstalowaniu tych bibliotek można je importować wraz z dodatkowymi modułami pochodzącymi z podstawowej biblioteki Pythona, zgodnie ze specyficznymi wymaganiami danej aplikacji lub zadania.
import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time
Wykorzystując bibliotekę Tkinter, opracuję atrakcyjny wizualnie graficzny interfejs użytkownika (GUI), który poprawi ogólne wrażenia użytkownika mojej aplikacji. Dodatkowo, wykorzystanie modułów os, threading i time zapewni niezbędne funkcje poprawiające wydajność systemu. Poprzez implementację współbieżności poprzez rozdzielenie niektórych części kodu na osobne wątki, zamierzam zoptymalizować wydajność wykonywania i usprawnić operacje.
Tworzenie katalogu galerii oraz definiowanie globalnych zmiennych i flag
Proces ten obejmuje utworzenie wyznaczonego folderu do przechowywania zarówno pozyskanych zdjęć, jak i nagranych materiałów wideo, zapewniając w ten sposób dostępność wymaganej przestrzeni dyskowej przed przechwyceniem lub nagraniem jakiejkolwiek treści wizualnej.
if not os.path.exists("gallery"):
os.makedirs("gallery")
Aby utworzyć zmienne do przechowywania miniatur zdjęć i filmów w albumie fotograficznym, musimy najpierw utworzyć dwie nowe struktury danych o nazwach “image\_thumbnails” i “video\_thumbnails”.
# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True
Flaga “update\_camera” służy do regulacji częstotliwości aktualizacji obrazu z kamery.
Przechwytywanie obrazów z kanału kamery
pythondef process_frame(camera):# Przechwyć klatkę z kanału kameryframe = cv2.imread(‘input_video.mp4’)# Zapisz klatkę w katalogu ‘gallery’ z unikalną nazwą pliku opartą na jego numerze indeksui = 0while True:filename = f"{i}.jpg “if not os.path.exists(‘gallery’):os.makedirs(“gallery”)retval = cv2.imwrite(filename, frame)i \+= 1# Wyświetl zapisaną klatkę za pomocą show_image
cv2.imshow(cv2.namedWindow(“Gallery”, cv2.WINDOW
def capture_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
Aby wyświetlić wideo, konieczne jest ustalenie metody jego generowania. W związku z tym opracujemy funkcję, która wyzwala rozpoczęcie nagrywania wideo na polecenie użytkownika, aby przechwycić wideo. Dodatkowo, funkcja ta dezaktywuje przycisk “Record” (w celu uniemożliwienia jednoczesnego nagrywania), aktywując jednocześnie przycisk “Stop Recording”. Ta czynność oznacza, że nagrywanie zostało zainicjowane.
def start_recording():
global video_writer, recording_start_time, recording_stopped, update_camera
if not 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 należy opracować funkcję, która zakończy proces przechwytywania wideo i zwolni koder wideo.
def stop_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)
Wyżej wymieniona funkcja wykonuje dodatkową operację aktualizacji interfejsu użytkownika, co pociąga za sobą aktywację przycisku “Nagraj” przy jednoczesnej dezaktywacji przycisku “Zatrzymaj nagrywanie”. Takie działania oznaczają, że proces nagrywania został zatrzymany.
Nagrywanie i wyświetlanie filmów
Prosimy o opracowanie funkcji, która będzie płynnie pobierać klatki ze źródła wideo, wykonywać niezbędne zadania przetwarzania i prezentować je w graficznym interfejsie użytkownika do czasu aktywacji polecenia “Zatrzymaj nagrywanie”. Wykonywanie tego procesu zostanie przerwane po wykonaniu wyżej wymienionej czynności.
def record_and_display():
global recording_stopped, update_camera
while video_writer and not 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)
Funkcjonalność tej funkcji obejmuje również obliczanie i wyświetlanie czasu trwania, w minutach i sekundach, który upłynął od rozpoczęcia nagrywania, w ramach każdej pojedynczej klatki wideo.
Wyświetlanie przechwyconych obrazów i filmów
Aby wyświetlić zawartość wizualną, która została pomyślnie pozyskana w procesie obrazowania i nagrywania wideo, wymagana jest odpowiednia metoda prezentacji.
Aby wyświetlić zawartość wizualną w interfejsie użytkownika, konieczne jest opracowanie funkcji, która pobiera plik obrazu z jego lokalizacji przechowywania, konwertuje go do formatu zgodnego z graficznym interfejsem użytkownika biblioteki Python Tkinter i aktualizuje wyświetlaną rzutnię o nowo pozyskane dane wizualne. Proces ten obejmuje wykorzystanie biblioteki Python Imaging Library (PIL) w celu uzyskania dostępu do przechowywanego obrazu i jego przetworzenia, a następnie zastosowanie odpowiednich metod graficznego interfejsu użytkownika Tkinter w celu włączenia przekształconego obrazu w wyznaczonym obszarze ekranu podglądu kamery.
def show_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ć nagrane filmy, należy zaimplementować funkcję, która aktywuje interfejs odtwarzania wideo umożliwiający oglądanie przechwyconego materiału. Dodatkowo, proces ten zawiesza wszelkie dalsze aktualizacje strumienia kamery w trakcie odtwarzania wideo.
def play_video(video_path):
def close_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)
def update_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)
wstrzymanie rozpowszechniania aktualizacji strumienia wideo przyczynia się do płynnej percepcji wizualnej.
Tworzenie miniatur wideo i otwieranie galerii
Włącz następujące stwierdzenie w wymowny sposób: Wdrożenie funkcji generowania miniatur jest uważane za niezbędne, ponieważ umożliwia użytkownikom szybkie rozpoznanie i wybranie żądanej zawartości wideo poprzez wizualnie zwięzłą reprezentację tego samego.
def create_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)
return None, None
Utwórz nową funkcję JavaScript o nazwie “playVideo”, która będzie uruchamiana po kliknięciu miniatury wideo w oknie galerii. Funkcja ta powinna inicjować odtwarzanie wybranego filmu i wyświetlać go w kontenerze odtwarzacza wideo.
def play_video_from_thumbnail(video_path):
play_video(video_path)
Jasne, oto przykład, jak można zaimplementować tę funkcjonalność w Pythonie przy użyciu biblioteki OpenCV:pythonimport cv2import numpy as npfrom tkinter import Tk, Frame, Button, Label, Text, Scrollbar, VERTICAL)def save_captured_frames(window):# Zdefiniuj parametry przechwytywania (można je zmienić, aby dostosować rozdzielczość, liczbę klatek na sekundę itp. )cap = cv2.VideoCapture(0)fourcc = cv2.VideoWriter_fourcc(*“mp4v”)fps = int(cap.get(cv2.CAP_PROP_FPS))width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
def open_gallery():
global update_camera
update_camera = False
gallery_window = tk.Toplevel(root)
gallery_window.title("Gallery")
def back_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)
def show_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("<Button-1>", 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()
Generowanie reprezentacji miniatur jest rozszerzone, aby pomieścić zarówno nieruchome obrazy, jak i ruchome obrazy, umożliwiając w ten sposób użytkownikom dostęp do odpowiadających im oryginalnych treści poprzez kliknięcie tych wizualnych podsumowań, a następnie przeglądanie pełnowymiarowego obrazu lub wyświetlanie produkcji kinowej.
Tworzenie głównego interfejsu użytkownika dla aplikacji
Rozpocznij proces od skonstruowania głównego interfejsu tkinter, a następnie nadaj mu wyróżniającą nazwę.
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 dla 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)
Wykorzystanie menedżera układu siatki jest skuteczną strategią rozmieszczania przycisków w głównym oknie aplikacji, zapewniając atrakcyjną wizualnie i zorganizowaną prezentację, zapewniając jednocześnie łatwość dostępu i interakcji z każdym przyciskiem.
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)
Włączenie funkcji wyświetlania obrazu z kamery w interaktywnym graficznym interfejsie użytkownika poprzez ustanowienie niezbędnych połączeń z komponentami sprzętowymi urządzenia, skonfigurowanie odpowiednich ustawień dla optymalnej wizualizacji i zainicjowanie odpowiedniego modułu lub biblioteki w celu renderowania strumienia wideo z kamery w wyznaczonym obszarze ekranu po uruchomieniu aplikacji lub po wyświetleniu monitu przez użytkownika.
camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)
Jasne! Oto przykład implementacji tej funkcji przy użyciu OpenCV i Pythona:pythonimport cv2from tkinter import *import threadingimport timedef update_camera_feed():# Inicjalizacja urządzenia do przechwytywania wideo devicecap = cv2.VideoCapture(0)while True:# Odczytaj klatkę ze strumienia wideoret, frame = cap.read()if not ret:break# Wyświetl klatkę na GUIlabel.config(image=frame)# Czekaj na naciśnięcie klawisza, aby wyjść z looproot.update()event = root.wait_event()if event == ‘q’:
def update_camera_feed():
if update_camera:
if not 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()
Na koniec uruchom pętlę maintkinterevent.
root.mainloop()
Obecna pętla odgrywa kluczową rolę w zarządzaniu zaangażowaniem użytkowników i ułatwianiu ich interakcji z systemem.
Testowanie funkcji aplikacji
Treść prezentacji przedstawia szereg funkcji, które są prezentowane przez aplikację, podkreślając jej możliwości i wszechstronność w działaniu.
Twoja przeglądarka nie obsługuje tagu wideo.
Doskonalenie umiejętności Pythona z OpenCV
OpenCV jest powszechnie uznawany za wiodące narzędzie do zastosowań wizji komputerowej, dzięki kompatybilności z szeroką gamą bibliotek, które ułatwiają rozwój różnych innowacyjnych projektów. Co więcej, użytkownicy mają możliwość wykorzystania jego możliwości za pośrednictwem Pythona, który służy jako doskonała platforma do doskonalenia umiejętności programistycznych.