Сбор данных и схема классов
Уроки курсаСбор данных и схема классов
Практика: собрать 300 изображений (или взять демо-пак)
Для обучения детектора нужны данные. Минимум 300 изображений (лучше 1000+), разнообразные — разные углы, освещение, фоны. Три варианта: скачать публичный датасет (COCO subset, Open Images), собрать свои фото, использовать демо-пак из курса. Проверяем качество (не размытые, не слишком мелкие), лицензию (можно ли использовать коммерчески), разнообразие классов.
Ключевые идеи
- Минимум 300 изображений на класс для приемлемого качества, 1000+ для хорошего.
- Разнообразие важнее количества: разные ракурсы, условия, фоны.
- Проверяем лицензию: Creative Commons, Public Domain — можно использовать.
- Качество: разрешение ≥640px, не размытые, объекты видны чётко.
- Демо-пак для быстрого старта — 300 размеченных изображений из курса.
Вариант 1: Публичные датасеты
Быстрый способ — скачать subset популярного датасета.
COCO subset:
# Скачать subset COCO (например, только категории person, car, dog)
# Используем fiftyone для фильтрации
pip install fiftyone
python <<EOF
import fiftyone as fo
import fiftyone.zoo as foz
# Загружаем COCO train split
dataset = foz.load_zoo_dataset(
"coco-2017",
split="train",
label_types=["detections"],
classes=["person", "car", "dog"], # Только нужные классы
max_samples=300 # Ограничение количества
)
# Экспортируем в YOLO формат
dataset.export(
export_dir="data/coco_subset",
dataset_type=fo.types.YOLOv5Dataset,
label_field="ground_truth"
)
EOF
Open Images subset:
# Скачать Open Images с помощью OIDv4 toolkit
pip install oidv4-toolkit
# Скачать 300 изображений класса "Car"
oidv4 downloader --classes Car --type_csv train --limit 300
Вариант 2: Собственные фото
Если задача специфична (дефекты продукции, редкие объекты), собираем сами.
Что учитывать:
- Разнообразие ракурсов: сверху, сбоку, снизу, крупный план, общий план.
- Условия съёмки: день/ночь, солнце/тень, разные фоны.
- Качество: не размытые, объект занимает 10-80% кадра (не слишком мелкий/крупный).
- Камеры: используйте разные устройства (телефон, камера) — модель будет robustнее.
Пример скрипта для сбора с веб-камеры:
import cv2
from pathlib import Path
def capture_images(output_dir, num_images=300):
"""Захватывает изображения с веб-камеры."""
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
cap = cv2.VideoCapture(0)
count = 0
print(f"Нажмите SPACE для захвата, ESC для выхода")
print(f"Цель: {num_images} изображений")
while count < num_images:
ret, frame = cap.read()
if not ret:
break
# Отображаем счётчик
cv2.putText(frame, f"Captured: {count}/{num_images}", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('Capture', frame)
key = cv2.waitKey(1)
if key == 27: # ESC
break
elif key == 32: # SPACE
filename = output_dir / f"image_{count:04d}.jpg"
cv2.imwrite(str(filename), frame)
print(f"Сохранено: {filename}")
count += 1
cap.release()
cv2.destroyAllWindows()
print(f"Захвачено {count} изображений")
# Использование
capture_images("data/raw/captured", num_images=300)
Вариант 3: Скачивание из интернета
Скачиваем с сайтов с открытыми лицензиями (Unsplash, Pexels).
Пример скрипта:
import requests
from pathlib import Path
import time
def download_images(urls, output_dir):
"""Скачивает изображения по списку URL."""
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
successful = 0
failed = 0
for i, url in enumerate(urls):
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
# Определяем расширение из Content-Type или URL
ext = url.split('.')[-1].split('?')[0]
if ext not in ['jpg', 'jpeg', 'png']:
ext = 'jpg'
filename = output_dir / f"image_{i:04d}.{ext}"
filename.write_bytes(response.content)
print(f"✓ Скачано: {filename.name}")
successful += 1
time.sleep(0.5) # Чтобы не заблокировали
except Exception as e:
print(f"✗ Ошибка {url}: {e}")
failed += 1
print(f"\nГотово: {successful} успешно, {failed} ошибок")
# Пример: список URL (замените на реальные)
urls = [
"https://images.unsplash.com/photo-1?w=640",
"https://images.pexels.com/photo-2?w=640",
# ... добавить 300 URL
]
download_images(urls, "data/raw/downloaded")
Важно: проверьте лицензию каждого сайта. Unsplash License, Pexels License — бесплатно, можно использовать коммерчески.
Демо-пак: если не хотите сразу собирать свои данные, скачайте учебный датасет на 300 размеченных изображений кошек и собак в YOLO-формате:
Скачать cv-demo-pet-300-yolo.zip
Проверка качества изображений
Скрипт для проверки разрешения и валидности:
from PIL import Image
from pathlib import Path
def check_images(images_dir, min_resolution=640):
"""Проверяет качество изображений."""
images_dir = Path(images_dir)
valid = 0
invalid = []
for img_path in images_dir.glob('*.jpg'):
try:
img = Image.open(img_path)
w, h = img.size
# Проверка минимального разрешения
if min(w, h) < min_resolution:
invalid.append(f"{img_path.name}: разрешение {w}x{h} < {min_resolution}px")
else:
valid += 1
except Exception as e:
invalid.append(f"{img_path.name}: ошибка открытия - {e}")
print(f"Проверено: {valid + len(invalid)} изображений")
print(f"Валидных: {valid}")
print(f"Невалидных: {len(invalid)}")
if invalid:
print("\nПроблемные файлы:")
for issue in invalid[:10]: # Показываем первые 10
print(f" {issue}")
check_images("data/raw/downloaded", min_resolution=640)
Частые проблемы
- Мало разнообразия: все фото с одного ракурса — модель переобучится. Снимайте с разных углов, расстояний.
- Низкое качество: размытые, тёмные, мелкие объекты. Модель не научится их детектировать. Фильтруйте плохие изображения.
- Нарушение лицензии: скачали с Google Images без проверки — могут быть авторские права. Используйте только открытые источники.
- Неправильные форматы: PNG вместо JPG, HEIC с iPhone. Конвертируйте в JPG/PNG для совместимости.
- Дубликаты: одно изображение попало в train и val — завышенные метрики. Проверьте уникальность (по хешу).
Проверка на дубликаты
import hashlib
from pathlib import Path
def find_duplicates(images_dir):
"""Находит дубликаты по хешу."""
hashes = {}
duplicates = []
for img_path in Path(images_dir).rglob('*.jpg'):
with open(img_path, 'rb') as f:
file_hash = hashlib.md5(f.read()).hexdigest()
if file_hash in hashes:
duplicates.append((img_path, hashes[file_hash]))
else:
hashes[file_hash] = img_path
if duplicates:
print(f"Найдено {len(duplicates)} дубликатов:")
for dup, original in duplicates[:5]:
print(f" {dup.name} = {original.name}")
else:
print("Дубликатов не найдено")
find_duplicates("data/images/")
Связанные понятия
- Web scraping: автоматический сбор изображений с сайтов (BeautifulSoup, Scrapy).
- Synthetic data: генерация синтетических изображений (Blender, Unity) для аугментации.
- Active learning: модель сама выбирает, какие изображения нужны для улучшения.
Итоги
- Минимум 300 изображений на класс, лучше 1000+ для хорошего качества.
- Варианты: публичные датасеты (быстро), собственные фото (специфичные задачи).
- Проверяем качество: разрешение ≥640px, не размытые, разнообразные.
- Лицензия: Unsplash, Pexels, Creative Commons — безопасно для коммерции.
- Валидация: проверяем разрешение, форматы, дубликаты перед разметкой.
Дальше по курсу
В следующем шаге создадим data.yaml для собранных изображений, проверим пути (все ли файлы на месте), разобьём на train/val/test с помощью скрипта. Подготовим датасет к разметке в CVAT или LabelImg.
