Следвайте този цялостен проект, за да научите повече за Python и обработката на изображения.
Независимо дали искате да работите върху ангажиращ Python проект или да изследвате различни аспекти на програмирането на Python, създаването на приложение за камера служи за тази цел. Това включва комбиниране на различни аспекти на програмирането на Python, като например разработка на графичен потребителски интерфейс (GUI), обработка на изображения и видео и многопоточност.
Освен това решаването на практически предизвикателства като това помага да изострите уменията си за решаване на проблеми. Тези умения са ценни във всяко начинание по програмиране.
Настройване на вашата среда
Започнете от създаване на нова виртуална среда. Това ще изолира вашия проект и ще гарантира, че няма конфликт между различните версии на пакетите, които инсталирате. След това изпълнете тази терминална команда:
pip install opencv-python pillow
Тази команда ще инсталира OpenCV библиотека и PIL (Python Imaging Library) във вашата виртуална среда. Ще използвате OpenCV за функционалност на компютърното зрение и PIL за манипулиране на изображения.
Пълният изходен код на този проект е достъпен в a GitHub хранилище.
Импортиране на необходимите библиотеки
След като инсталирате тези библиотеки, можете да ги импортирате заедно с други необходими модули от стандартната библиотека на Python:
import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time
Вие ще използване tkinter за създаване на графичен потребителски интерфейс за вашето приложение и модулите за операционна система, нишки и време за свързаната с тях функционалност. Като разделите част от кода си на нишки, вие ще активирайте го да работи едновременно.
Създаване на директория на галерия и дефиниране на глобални променливи и флагове
Създайте директория за съхраняване на заснети изображения и записани видеоклипове. Тази стъпка ще гарантира, че директорията съществува, преди да продължите да заснемате или записвате видеоклипове.
ifnot os.path.exists("gallery"):
os.makedirs("gallery")
След това дефинирайте изображения_миниатюри и video_thumbnails променливи. Те ще съхраняват миниатюри на изображения и видеоклипове в галерията.
# Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True
The актуализация_камера флагът ще контролира актуализациите на емисиите на камерата.
Заснемане на изображения от канала на камерата
Дефинирайте функция, която ще използва OpenCV за заснемане на изображение от емисията на камерата. След това трябва да извлече кадър от камерата, да го запише в галерия директория и я покажете с помощта на покажи_изображение.
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)
Стартиране и спиране на видеозапис
Преди да покажете видеоклип, имате нужда от начин да го създадете. За да постигнете това, създайте функция, която инициира процеса на видеозапис, когато потребителят иска да заснеме видео. Функцията също трябва да деактивира Записвайте (за предотвратяване на няколко записа едновременно) и активирайте Спрете записа бутон. Това показва, че записът е в ход.
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()
След това създайте функция, която спира видеозаписа и освобождава видеозаписвача.
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)
Тази функция също актуализира потребителския интерфейс, позволявайки на Записвайте бутон и деактивиране на Спрете записа бутон. Това показва, че записът е спрял.
Записване и показване на видеоклипове
Създайте функция, която непрекъснато ще заснема кадри от камерата, ще ги обработва и ще ги показва в графичния потребителски интерфейс като канал на камерата. Трябва да го направи, освен ако Спрете записа е натиснат бутон.
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)
Функцията също изчислява изминалото време от началото на записа и го показва на видеокадъра.
Показване на заснети изображения и видеоклипове
Сега, след като сте заснели изображенията и сте записали видеоклиповете, имате нужда от начин да ги покажете.
За да покажете изображенията, създайте функция, която отваря изображение и го показва в канала на камерата. Това се постига чрез отваряне на изображението с помощта на PIL, след което го конвертирате във формат, който tkinter може да се покаже и накрая актуализиране на приспособлението за емисии на камерата с новото изображение.
defshow_image(image_path):
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image=image)
camera_feed.config(image=photo)
camera_feed.image = photo
За да покажете заснетите видеоклипове, създайте функция, която отваря прозорец на видео плейър, където потребителят може да гледа записани видеоклипове. Той също така поставя на пауза актуализациите на емисиите на камерата, докато се възпроизвежда видеоклипът.
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)
Поставянето на пауза на актуализациите на емисиите на камерата гарантира гладко гледане.
Създаване на видео миниатюра и отваряне на галерията
Създайте функция, която ще генерира миниатюрно изображение за даден видеоклип. Това ще улесни потребителите при идентифицирането на интересния видеоклип.
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
След това създайте функция, която възпроизвежда видеоклип, когато потребител щракне върху миниатюрата на видеоклипа в прозореца на галерията:
defplay_video_from_thumbnail(video_path):
play_video(video_path)
След това създайте функция, която създава нов прозорец, където потребителят може да преглежда заснетите изображения и видеоклипове.
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()
Създават се миниатюри както за изображения, така и за видеоклипове. Това означава, че можете да щракнете върху тях, за да видите изображението в пълен размер или да възпроизведете видеоклипа.
Създаване на основния потребителски интерфейс за вашето приложение
Започнете със създаването на основния tkinter прозорец на приложението и след това му дайте заглавие.
root = tk.Tk()
root.title("Camera Application")
След това инициализирайте необходимите променливи.
video_writer = None
recording_start_time = 0# Initialize recording start time
recording_stopped = False# Initialize recording_stopped flag
След това създайте бутони за различни действия.
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)
Използвайте мениджъра за оформление на мрежата, за да организирате бутоните в главния прозорец.
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)
Създайте изпълним модул за показване на емисията от камерата и го инициализирайте.
camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)
След това създайте функция, която непрекъснато актуализира емисията на камерата, показана в tkinter прозорец.
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()
Накрая започнете основното tkinter цикъл на събитието.
root.mainloop()
Този цикъл е отговорен за обработката на потребителските взаимодействия.
Тестване на функциите на приложението
Този видеоклип демонстрира различни функции на приложението:
Изостряне на уменията ви за Python с OpenCV
OpenCV доминира, когато става въпрос за компютърно зрение. Работи с много различни библиотеки, което ви позволява да създавате много страхотни проекти. Можете да го използвате с Python, за да практикувате и изостряте уменията си за програмиране.