Создание системы распознавания объектов с YOLOv8 и Python

Создание системы распознавания объектов с YOLOv8 и Python

Современные технологии компьютерного зрения позволяют в реальном времени распознавать объекты через веб-камеру. В этой статье разберём создание собственного desktop-приложения на Python с использованием библиотеки OpenCV, нейросети YOLO и графического интерфейса на CustomTkinter.

Приложение умеет:

  • получать видео с камеры;
  • находить объекты в кадре;
  • отображать рамки вокруг объектов;
  • выводить список найденных предметов;
  • автоматически переводить названия объектов на русский язык;
  • работать как на CPU, так и на GPU через CUDA.

Основные библиотеки

Перед началом работы необходимо установить зависимости:

pip install customtkinter opencv-python pillow torch ultralytics

В проекте используются:

  • OpenCV — работа с камерой и изображениями;
  • PyTorch — запуск нейросети;
  • YOLO — распознавание объектов;
  • Pillow — обработка изображений;
  • CustomTkinter — современный интерфейс приложения.

Инициализация приложения

Главное окно создаётся через класс CameraApp.

class CameraApp(ctk.CTk):

Внутри конструктора выполняется:

  • запуск камеры;
  • загрузка модели YOLO;
  • определение устройства (CPU или GPU);
  • запуск циклов обновления интерфейса.
 
self.cap = cv2.VideoCapture(0)
self.model = YOLO('yolo26n.pt')
self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
self.model.to(self.device)
Если в системе доступна видеокарта NVIDIA и установлен CUDA, модель автоматически будет работать значительно быстрее.

Создание интерфейса

Интерфейс разделён на две части:

Левая часть

Содержит видеопоток с камеры.

 
self.video_label = ctk.CTkLabel(
self.video_frame,
text="",
fg_color="black"
)
 

Правая часть

Отображает список найденных объектов.

 
self.objects_listbox = ctk.CTkFrame(self.right_frame)
 

Для каждого найденного объекта создаётся отдельная кнопка.


Обработка видео с камеры

Главная логика находится в методе update_frame().

Получение кадра

 
ret, frame = self.cap.read()
 

Конвертация цветов

OpenCV использует формат BGR, а для корректного отображения нужен RGB.

 
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
 

Распознавание объектов через YOLO

Модель анализирует кадр:

 
results = self.model(frame, device=self.device, verbose=False)
 

После этого перебираются найденные объекты:

 
for box in results[0].boxes:
 

Получаем:

  • ID класса;
  • название объекта;
  • цвет рамки.
 
class_id = int(box.cls[0])
object_name = self.model.names[class_id]
 

Отображение рамок вокруг объектов

YOLO автоматически рисует bounding boxes:

 
img = Image.fromarray(results[0].plot())
 

В результате пользователь видит:

  • объект;
  • рамку;
  • название класса;
  • уровень уверенности модели.

Перевод объектов на русский язык

В проекте используется словарь:

 
from yolo_en_to_ru import yolo26_en_to_ru
 

Пример перевода:

 
object_name_ru = yolo26_en_to_ru.get(
object_name,
object_name
)
 

Например:

Английский Русский
person человек
car машина
dog собака

Динамический список объектов

Каждый обнаруженный объект выводится отдельной кнопкой.

 
btn_item = ctk.CTkButton(
self.objects_listbox,
text=display_text
)
 

При нажатии открывается модальное окно:

 
def click_btn(self, display_text):
 

Это можно использовать для:

  • дополнительной информации;
  • статистики;
  • озвучивания объекта;
  • сохранения данных.

Подсчёт объектов

Для группировки одинаковых объектов используется:

 
from collections import Counter
 

Пример:

 
object_counts = Counter(self.current_objects)
 

Если камера видит 3 человека и 2 телефона, приложение может корректно подсчитать количество каждого типа объектов.


Работа с GPU

Одно из главных преимуществ проекта — поддержка CUDA.

 
self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
 

Это позволяет:

  • увеличить FPS;
  • ускорить распознавание;
  • снизить нагрузку на процессор.

Преимущества проекта

Высокая скорость

YOLO обеспечивает распознавание объектов практически в реальном времени.

Современный интерфейс

CustomTkinter делает интерфейс более современным по сравнению с обычным Tkinter.

Простота расширения

Проект легко доработать:

  • добавить запись видео;
  • сохранять скриншоты;
  • подключить Telegram-бота;
  • добавить голосовое озвучивание;
  • интегрировать базу данных;
  • обучить собственную модель.

Возможные улучшения

Добавление трекинга объектов

Можно отслеживать движение объектов между кадрами.

Распознавание лиц

Интеграция с face recognition позволит определять конкретных людей.

Работа с IP-камерами

Вместо веб-камеры можно подключить RTSP-поток.

Экспорт статистики

Сохранять данные в:

  • CSV;
  • SQLite;
  • PostgreSQL;
  • Excel.

 

Данный проект — отличный пример использования современных технологий компьютерного зрения на Python. Сочетание YOLO, OpenCV и CustomTkinter позволяет создать мощное приложение для распознавания объектов в реальном времени.

Такое решение можно использовать для:

  • систем видеонаблюдения;
  • умного дома;
  • автоматизации;
  • анализа видео;
  • образовательных проектов;
  • AI-приложений.

Полный код

import customtkinter as ctk
import cv2
from PIL import Image
import torch
from collections import Counter
from yolo_en_to_ru import yolo26_en_to_ru
from ultralytics import YOLO
from ultralytics.utils.plotting import colors


class CameraApp(ctk.CTk):
def __init__(self):
super().__init__()
self.title('')
self.geometry('800x600')
self.resizable(False, False)
self.cap = cv2.VideoCapture(0)
self.model = YOLO('yolo26n.pt')
self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
self.model.to(self.device)
self.current_objects = []

print(f"Модель загружена на устройство: {self.model.device}")

if not self.cap.isOpened():
print('Ошибка: Камера не найдена')
#return

self.create_widgets()

self.update_frame()
self.objects_loop()

def create_widgets(self):

self.grid_columnconfigure(0, weight=3)
self.grid_rowconfigure(1, weight=1)
self.grid_rowconfigure(0, weight=1)

self.video_frame = ctk.CTkFrame(self)
self.video_frame.grid(row=0, column=0, padx=(20, 10), pady=20, sticky="nsew")
self.video_frame.rowconfigure(0, weight=1)
self.video_frame.grid_columnconfigure(0, weight=1)

self.video_label = ctk.CTkLabel(self.video_frame, text="", fg_color="black")
self.video_label.grid(row=0, column=0, padx=20, pady=20, sticky="nsew")

self.right_frame = ctk.CTkFrame(self)
self.right_frame.grid(row=0, column=1, padx=(10, 20), pady=20, sticky="nsew")
self.right_frame.grid_rowconfigure(1, weight=1)
self.right_frame.grid_columnconfigure(0, weight=1)

self.objects_listbox = ctk.CTkFrame(self.right_frame)
self.objects_listbox.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")

#self.objects_listbox = ctk.CTkTextbox(self.right_frame)
#self.objects_listbox.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")

def clear_frame(self, frame):
for widget in frame.winfo_children():
widget.destroy()

def click_btn(self, display_text):
modal_add_note = ctk.CTkToplevel()
ctk.CTkLabel(modal_add_note, text=display_text, font=(None, '33px')).pack()


def update_objects_list(self):
#self.objects_listbox.configure(state='normal')
#self.objects_listbox.delete('1.0', 'end')
self.clear_frame(self.objects_listbox)

if self.current_objects:
object_counts = Counter(self.current_objects)

for object_tuple, count in object_counts.items():
object_name = object_tuple[0]
color = object_tuple[1]
object_name_ru = yolo26_en_to_ru.get(object_name, object_name)
display_text = f'{object_name_ru}'
btn_item = ctk.CTkButton(self.objects_listbox, bg_color=color, command=lambda m=display_text: self.click_btn(m), text=display_text, anchor="center", height=5)
btn_item.pack(pady=10, padx=10)


#self.objects_listbox.insert('end', display_text)
#self.objects_listbox.configure(state='disabled')

def objects_loop(self):
self.update_objects_list()
self.after(3000, self.objects_loop)

def update_frame(self):
ret, frame = self.cap.read()
if ret:
# Конвертируем BGR в RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = self.model(frame, device=self.device, verbose=False)

detected_objects = []
if results[0].boxes is not None:
for box in results[0].boxes:
class_id = int(box.cls[0])
object_name = self.model.names[class_id]
box_color_rgb = colors(class_id, bgr=False)
hex_color_hex = f"#{box_color_rgb[0]:02x}{box_color_rgb[1]:02x}{box_color_rgb[2]:02x}"
detected_objects.append((object_name, hex_color_hex))

self.current_objects = detected_objects
self.after(3000, lambda: self.update_objects_list)

img = Image.fromarray(results[0].plot())

w, h = self.video_label.winfo_width(), self.video_label.winfo_height()
if w < 10: w, h = 640, 480
ctk_img = ctk.CTkImage(light_image=img, dark_image=img, size=(w, h))
self.video_label.configure(image=ctk_img)
self.video_label._image = ctk_img
self.after(20, self.update_frame)


ctk.set_appearance_mode('dark')
ctk.set_default_color_theme('blue')

app = CameraApp()
app.mainloop()

Автор:

8

Читайте также

0 комментариев

Оставьте комментарий

Комментарии

×
Подпишитесь на наше сообщество ВКонтакте, чтобы быть в курсе всех новостей и акций!
Подписаться