f14249dec953665f7ec3e644b050f61224d4ea1b
The core calibration was broken because the green quad corners didn't correspond to the correct court corners (giving Z=15m camera positions). New approach: 1. Detect white line segments on green court surface 2. Merge into distinct lines, find intersections 3. Match intersections to known court template using initial homography from green quad (tries both left-right mirror mappings) 4. solvePnP with matched 2D-3D correspondences 5. Sanity check: camera Z must be 0-5m, prefers ~1m height 6. Fallback to quad-only calibration with both mappings if not enough intersections detected Also: CameraCalibrator now uses findHomography for N>4 points, and get_half_court_intersections() provides the 6 template keypoints. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🎾 Pickle - Pickleball Ball Tracking
Система трекинга пикабольного мяча с автоматической детекцией корта и преобразованием координат в метры.
Что делает
- Детекция корта - автоматический поиск 4 углов корта (Roboflow модель)
- Детекция мяча - поиск мяча на каждом кадре (YOLO v8)
- Трансформация координат - преобразование пикселей в метры (homography)
- Визуализация - видео с траекторией, графики, тепловая карта
Быстрый старт
# Запуск
docker-compose up -d
# Открыть Dagster UI
open http://localhost:3000
# Запустить пайплайн
docker exec pickle-dagster dagster asset materialize --select '*' -m dagster_project
Структура пайплайна
1. extract_video_frames → Извлекает 100 кадров (с 10-й секунды)
↓
2. detect_court_keypoints → Находит 4 угла корта
↓ ↓
3. detect_ball_positions ←┘ Детектит мяч на всех кадрах
↓
4. compute_2d_coordinates → Преобразует пиксели в метры
↓
5. visualize_trajectory → Создает визуализации
Результаты
После выполнения пайплайна в data/:
- extract_video_frames.json - метаданные видео
- detect_court_keypoints.json - координаты углов корта
- detect_ball_positions.json - позиции мяча в пикселях
- compute_2d_coordinates.json - позиции мяча в метрах
- visualization.mp4 - видео с траекторией, кортом и координатами
- frames/ - извлеченные кадры
- ball_detections/ - кадры с найденным мячом
- court_detection_preview.jpg - превью с найденными углами корта
Структура проекта
pickle/
├── dagster_project/ # Dagster пайплайн
│ ├── assets/ # 5 asset'ов пайплайна
│ └── io_managers/ # JSON IO manager
├── src/ # Основной код
│ ├── ball_detector.py # YOLO детекция
│ ├── court_calibrator.py # Калибровка корта
│ ├── ball_tracker.py # Трекинг
│ └── video_processor.py # Обработка видео
├── data/ # Результаты выполнения
├── DJI_0017.MP4 # Видео для обработки
├── docker-compose.yml
└── Dockerfile
Конфигурация
Параметры в dagster_project/assets/:
- video_extraction.py -
start_sec=10,num_frames=100 - ball_detection.py -
confidence_threshold=0.3, slicing 320x320 - coordinate_transform.py - корт 13.4м × 6.1м
Модели
- Корт:
ping-pong-paddle-ai-with-images/pickleball-court-p3chl-7tufp(Roboflow) - Мяч:
pickleball-detection-1oqlw/1(Roboflow) → fallback на YOLOv8n
Требования
- Docker & Docker Compose
- 4GB+ RAM
- Видео файл
DJI_0017.MP4в корне проекта
Docker команды
# Билд и запуск
docker-compose up --build -d
# Логи
docker-compose logs -f
# Остановка
docker-compose down
# Выполнить пайплайн
docker exec pickle-dagster dagster asset materialize --select '*' -m dagster_project
# Выполнить один asset
docker exec pickle-dagster dagster asset materialize --select 'detect_ball_positions' -m dagster_project
Dagster UI
Показывает:
- Граф зависимостей между assets
- Логи выполнения
- История запусков
- Метаданные результатов
Формат данных
compute_2d_coordinates.json:
[
{
"frame": 6,
"timestamp": 0.2,
"pixel_x": 1234.5,
"pixel_y": 678.9,
"x_m": 5.67,
"y_m": 2.34,
"confidence": 0.85
}
]
Производительность
- Извлечение кадров: ~1 сек
- Детекция корта: ~1 сек
- Детекция мяча: ~6 сек (100 кадров, ~15 FPS)
- Трансформация координат: <1 сек
- Визуализация: ~1 сек
Итого: ~10 секунд на 100 кадров видео
Стоимость
$0 - всё работает локально в Docker, без облачных API
License
MIT
Description
Languages
Python
62.5%
HTML
37%
Dockerfile
0.3%
Shell
0.2%