Следуйте этому комплексному проекту, чтобы узнать больше о Python и обработке изображений.

Хотите ли вы поработать над интересным проектом на Python или изучить различные аспекты программирования на Python, создание приложения для камеры служит этой цели. Он включает в себя объединение различных аспектов программирования на Python, таких как разработка графического пользовательского интерфейса (GUI), обработка изображений и видео, а также многопоточность.

Кроме того, решение практических задач, подобных этой, помогает отточить ваши навыки решения проблем. Эти навыки ценны в любом начинании программирования.

Настройка среды

Начать с создание новой виртуальной среды. Это изолирует ваш проект и гарантирует отсутствие конфликтов между различными версиями устанавливаемых вами пакетов. Затем запустите эту команду терминала:

pip install opencv-python pillow

Эта команда установит OpenCV библиотека и ПИЛ (Библиотека изображений Python) в вашей виртуальной среде. Вы будете использовать OpenCV для функций компьютерного зрения и PIL для манипулирования изображениями.

instagram viewer

Полный исходный код этого проекта доступен в Репозиторий GitHub.

Импорт необходимых библиотек

После установки этих библиотек вы можете импортировать их вместе с другими необходимыми модулями из стандартной библиотеки Python:

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

Вы будете использовать Ткинтер создать графический интерфейс пользователя для вашего приложения и операционной системы, модулей потоковой обработки и времени для связанных с ними функций. Разделив часть вашего кода на потоки, вы включить его для одновременной работы.

Создание каталога галереи и определение глобальных переменных и флагов

Создайте каталог для хранения захваченных изображений и записанных видео. Этот шаг позволит убедиться, что каталог существует, прежде чем приступить к захвату или записи видео.

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

Затем определите image_thumbnails и video_thumbnails переменные. Они будут хранить миниатюры изображений и видео в галерее.

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

update_camera флаг будет контролировать обновления каналов камеры.

Захват изображений с камеры

Определите функцию, которая будет использовать OpenCV для захвата изображения с камеры. Затем он должен получить кадр с камеры и сохранить его в папке галерея каталог и отобразите его с помощью 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)

Запуск и остановка записи видео

Прежде чем отображать видео, вам нужен способ его создания. Для этого создайте функцию, которая инициирует процесс записи видео, когда пользователь хочет записать видео. Функция также должна отключить Записывать кнопку (чтобы предотвратить одновременную запись нескольких записей) и включите Остановить запись кнопка. Это означает, что запись идет.

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

Затем создайте функцию, которая останавливает запись видео и освобождает программу записи видео.

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

Функция также вычисляет время, прошедшее с момента начала записи, и отображает его на видеокадре.

Отображение захваченных изображений и видео

Теперь, когда вы сделали снимки и записали видео, вам нужен способ их отображения.

Чтобы отобразить изображения, создайте функцию, которая открывает изображение и отображает его в канале камеры. Это достигается путем открытия изображения с помощью ПИЛ, а затем преобразую его в формат, который Ткинтер может отобразить и, наконец, обновить виджет камеры новым изображением.

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

Приостановка обновлений каналов камеры обеспечивает плавность просмотра.

Создание миниатюры видео и открытие галереи

Создайте функцию, которая будет генерировать миниатюру для данного видео. Это облегчит пользователям определение интересующего видео.

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

Миниатюры создаются как для изображений, так и для видео. Это означает, что вы можете нажать на них, чтобы просмотреть полноразмерное изображение или воспроизвести видео.

Создание основного пользовательского интерфейса для вашего приложения

Начните с создания основного Ткинтер окно приложения, а затем дайте ему название.

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)

Затем создайте функцию, которая будет постоянно обновлять изображение с камеры, отображаемое в Ткинтер окно.

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

Наконец, запустите основной Ткинтер цикл событий.

root.mainloop()

Этот цикл отвечает за обработку взаимодействия с пользователем.

Тестирование функций приложения

В этом видео демонстрируются различные возможности приложения:

Оттачивайте свои навыки Python с помощью OpenCV

OpenCV доминирует, когда дело касается компьютерного зрения. Он работает со множеством различных библиотек, что позволяет вам создавать множество интересных проектов. Вы можете использовать его с Python, чтобы практиковать и совершенствовать свои навыки программирования.