Ultralytics YOLO27: Встать в лист ожидания.
Get Started
Основы компьютерного зрения·Сформулируй задачу·Урок 1/10
Урокначинающий

Сформулируй задачу

Преврати расплывчатую идею продукта в спецификацию задачи из трёх строк, а бизнес-правило храни в коде, где его можно изменить без переобучения.

Залитый солнцем городской перекрёсток, вид сверху: Ultralytics YOLO выделяет рамками пешеходов, велосипедистов, автобус и автомобили

Большинство проектов в области компьютерного зрения, которые заходят в тупик, изначально не имели чёткого вопроса. «Выявлять небезопасное поведение» звучит как требование, но разметчик не может это разметить, модель не может этому научиться, а понять, работает ли решение, никто не сможет. Спецификация из трёх строк решает эту проблему за один день и определяет, какую задачу ты будешь обучать, что размечать и какую метрику представлять.

Результат

Составь спецификацию задачи из трёх строк (входные данные, результат, решение) и реализуй принятие решения в коде, который обрабатывает результаты YOLO26.

Ускоренное прохождение
Если ты уже освоился, вот краткая версия.
  1. Входные данные: источник, разрешение, частота кадров и сцена.

  2. Результат: тип данных — метка, рамки, маски, ключевые точки или карта по пикселям, но не действие.

  3. Решение: кто действует, когда и по какому правилу.

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

  5. Проверь правило на реальных результатах, прежде чем ему доверять: пересечение на изображении не означает физическую близость.

Практические занятия

Почему спецификация нужна в первую очередь#

Этапы проекта компьютерного зрения с 0-го по 4-й: подготовка основы, сбор и подготовка данных, разработка признаков и модели, развёртывание модели и мониторинг модели

Каждый этап проекта компьютерного зрения наследует целевой ориентир от нулевого этапа. Расплывчатый вопрос приводит к расплывчатому датасету, разногласиям между разметчиками и метрике, измеряющей не то, что нужно. И никакое обучение на втором этапе этого не исправит.

Три строки#

Спецификация задачи состоит из трёх предложений, по одному в каждой строке. Каждое отвечает на вопрос, который задаст участник проекта:

СтрокаНа какой вопрос отвечаетСлабоХорошо
Входные данныеЧто видит модель?«Видеозапись с камеры»«Кадры 1920×1080 с частотой 5 кадров/с с 12 потолочных камер»
РезультатКакие данные возвращаются?«Выявлять проблемы с безопасностью»«Рамки для forklift и person, каждая с оценкой уверенности»
РешениеКто действует и когда?«Повысить безопасность»«Отправить уведомление начальнику смены, если погрузчик находится ближе 2 м к человеку в течение 2 с»

Особенно внимательно формулируй строку с результатом, потому что тип данных определяет задачу:

Результаты семи задач Ultralytics YOLO рядом: детекция, поза, сегментация, классификация, OBB, семантическая сегментация и глубина

Одна метка для всего изображения означает классификацию; рамки — детекцию; контуры — сегментацию; суставы — позу; повёрнутые рамки — OBB; класс или расстояние для каждого пикселя — семантическую сегментацию или глубину. В следующем уроке рассматриваются все семь задач.

Пример: отделяем модель от правила#

«Мы хотим знать, когда погрузчики делают что-то опасное на складе».

Это описание проекта, а не задачи. Оно объединяет две работы: поиск погрузчиков и людей — задача, связанная с пикселями, — и определение того, что считать опасным, — вопрос правил. Раздели их:

Моделью является только детектор. Ромб — это обычный код. Попробуй разделить их прямо сейчас: на bus.jpg нет погрузчика, но автобус и четыре человека подойдут для той же проверки. Первое правило звучит так: «отправлять оповещение, если рамки человека и транспортного средства перекрываются более чем на 30 %»:

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]

# The model's job ends here: a class, a box, and a confidence per object.
people = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "person"]
vehicles = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "bus"]

def share_inside(a, b):
    """Fraction of box a's area that lies inside box b."""
    w = max(0, min(a[2], b[2]) - max(a[0], b[0]))
    h = max(0, min(a[3], b[3]) - max(a[1], b[1]))
    return w * h / ((a[2] - a[0]) * (a[3] - a[1]))

# The decision rule is plain code: change the policy without retraining.
ALERT_SHARE = 0.30
for person in people:
    share = max(share_inside(person, v) for v in vehicles)
    print(f"person at x={person[0]:3.0f}: {share:4.0%} inside the bus box -> {'ALERT' if share > ALERT_SHARE else 'ok'}")
person at x= 49:  70% inside the bus box -> ALERT
person at x=223:  76% inside the bus box -> ALERT
person at x=670:  70% inside the bus box -> ALERT
person at x=  0:  62% inside the bus box -> ALERT

Четыре оповещения — и все ложные: люди идут по тротуару перед припаркованным автобусом. Детектор правильно определил все рамки; ошибочно правило, ведь перекрытие на 2D-изображении не означает, что два объекта находятся близко друг к другу в реальном мире. Поскольку правило — это код, исправлять нужно код. Сравни положение ног каждого человека на земле с линией колёс автобуса:

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
people = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "person"]
vehicles = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "bus"]

def same_ground_line(person, vehicle, tolerance=40):
    """True when the person's feet are level with the vehicle's wheels and inside its width."""
    feet_x, feet_y = (person[0] + person[2]) / 2, person[3]
    return vehicle[0] < feet_x < vehicle[2] and abs(feet_y - vehicle[3]) < tolerance

for person in people:
    alert = any(same_ground_line(person, v) for v in vehicles)
    print(f"person at x={person[0]:3.0f}: feet y={person[3]:.0f}, bus wheels y={vehicles[0][3]:.0f} -> {'ALERT' if alert else 'ok'}")
person at x= 49: feet y=902, bus wheels y=751 -> ok
person at x=223: feet y=861, bus wheels y=751 -> ok
person at x=670: feet y=880, bus wheels y=751 -> ok
person at x=  0: feet y=871, bus wheels y=751 -> ok

Ноги каждого человека находятся на 110–150 пикселей ниже линии колёс, значит, люди стоят ближе к камере, чем автобус. Переобучение и повторная разметка не нужны: команда по безопасности дорабатывает правило, а детектор остаётся без изменений. В рабочей версии положение ног можно было бы переводить в координаты пола с помощью калиброванной камеры, а двухсекундное условие непрерывности реализовать через отслеживание объектов — всё это по-прежнему код поверх тех же рамок.

Вынеси правила из модели

Субъективные слова — «небезопасный», «дефектный», «подозрительный», «VIP» — должны использоваться в коде, который обрабатывает вывод модели. Модель отвечает на вопросы о пикселях. Если два эксперта поспорят о метке, этот спор должен быть разрешён правилом, которое можно версионировать, тестировать и менять.

Подводные камни#

Выходная строка — это действие

Симптом: в спецификации написано «обнаруживать проблемы с безопасностью» или «понимать сцену», и разметчики спрашивают, что именно нужно рисовать. Решение: опиши выход как тип данных с именованными классами: «рамки для forklift и person».

Класс, на который нельзя указать

Симптом: два разметчика по-разному размечают один и тот же кадр для класса вроде suspicious_behavior или dangerous. Решение: замени его на видимое свидетельство — человека в закрытой зоне, дверь, которую удерживают открытой, — а оценочное суждение перенеси в строку решения.

Выход — это предложение или прогноз

Симптом: «опиши происходящее» (создание описаний) или «предскажи, заденет ли погрузчик человека» (прогнозирование). Решение: сначала найди объекты, затем добавь поверх этого правила трекинга и движения. Создай детектор до разработки предсказаний.

От спецификации к критериям успеха#

Спецификация определяет, что делает модель, но не то, какой результат достаточно хорош и во сколько обходится пропуск по сравнению с ложным срабатыванием. В материале «Начни с бизнес-цели» из курса «Создание высокопроизводительных датасетов YOLO» спецификация превращается в измеримые целевые показатели. Каждый следующий урок этого курса опирается на три строки твоей спецификации.

Попробовать

Составь спецификацию из трёх строк для своего проекта — или для магазинной камеры, которая должна отмечать пустые места на полках. Ограничь каждую строку одним предложением. Затем перечисли все слова в строке решения, которые модель не может увидеть на пикселях, и запиши решение как однострочное правило для результатов модели (подойдёт псевдокод).

Критерии готовности
Урок считается завершённым, если выполнены все условия ниже.
  • В строке входных данных укажи источник, разрешение и частоту кадров.

  • В строке результата укажи тип данных с названиями классов, а не действие.

  • Запиши решение как правило для результатов модели, а все субъективные понятия оставь в этом правиле, а не в названиях классов.

Показать решение

Спецификация для камеры, направленной на полку:

  • Входные данные: один неподвижный кадр 1920×1080 каждые 60 секунд с камеры, направленной на один проход.
  • Результат: рамки для product и empty_facing (место на полке без товара), каждая с оценкой уверенности.
  • Решение: создать задачу на пополнение запасов, если на одной полке в течение пяти последовательных кадров в часы работы магазина сохраняются три или более рамки empty_facing.

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

if count(empty_facing on shelf S) >= 3 in each of the last 5 stills and store_is_open(now):
    create_restock_task(shelf=S)

Магазин может изменить «3», «5» или часы работы, не размечая ни одного изображения.

Что дальше

Далее: семь задач, которые поддерживает Ultralytics YOLO, и способ сопоставить строку результата ровно с одной из них.

Войди, чтобы сохранять прогресс