System Development мониторинга парковки через видеоаналитику
Система видеоаналитики парковки заменяет дорогостоящие ультразвуковые и магнитные датчики на каждое машиноместо единой камерой, покрывающей несколько рядов. Задачи: определение занятости мест в реальном времени, подсчёт свободных/занятых мест, трекинг автомобилей, интеграция с системой навигации по парковке.
Определение занятости машиномест
from ultralytics import YOLO
import numpy as np
import cv2
import json
class ParkingMonitor:
def __init__(self, model_path: str, parking_config_path: str):
self.detector = YOLO(model_path) # детекция автомобилей
self.parking_spaces = self._load_parking_config(parking_config_path)
def _load_parking_config(self, config_path: str) -> list[dict]:
"""Загрузка конфигурации машиномест (полигоны зон)"""
with open(config_path) as f:
config = json.load(f)
spaces = []
for space in config['spaces']:
spaces.append({
'id': space['id'],
'polygon': np.array(space['polygon'], dtype=np.int32),
'zone': space.get('zone', 'default')
})
return spaces
def analyze(self, frame: np.ndarray) -> dict:
"""Определение занятости всех машиномест"""
detections = self.detector(frame, conf=0.4,
classes=[2, 5, 7]) # car, bus, truck
# Определяем центры обнаруженных ТС
vehicle_centers = []
for box in detections[0].boxes.xyxy:
x1, y1, x2, y2 = map(int, box)
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2
vehicle_centers.append((cx, cy))
# Проверяем каждое машиноместо
occupied_spaces = []
free_spaces = []
for space in self.parking_spaces:
occupied = self._is_space_occupied(space['polygon'],
vehicle_centers,
detections[0].boxes.xyxy)
space_status = {
'id': space['id'],
'zone': space['zone'],
'occupied': occupied
}
if occupied:
occupied_spaces.append(space_status)
else:
free_spaces.append(space_status)
return {
'total_spaces': len(self.parking_spaces),
'occupied': len(occupied_spaces),
'free': len(free_spaces),
'occupancy_rate': len(occupied_spaces) / max(len(self.parking_spaces), 1),
'spaces': occupied_spaces + free_spaces
}
def _is_space_occupied(self, polygon: np.ndarray,
vehicle_centers: list,
vehicle_boxes: list) -> bool:
"""Проверка: есть ли транспортное средство на машиноместе"""
# Метод 1: центр ТС внутри полигона
for cx, cy in vehicle_centers:
result = cv2.pointPolygonTest(polygon, (float(cx), float(cy)), False)
if result >= 0:
return True
# Метод 2: overlap bounding box с полигоном > 40%
space_mask = np.zeros((720, 1280), dtype=np.uint8)
cv2.fillPoly(space_mask, [polygon], 255)
space_area = cv2.contourArea(polygon)
for box in vehicle_boxes:
x1, y1, x2, y2 = map(int, box)
vehicle_mask = np.zeros_like(space_mask)
cv2.rectangle(vehicle_mask, (x1, y1), (x2, y2), 255, -1)
intersection = cv2.bitwise_and(space_mask, vehicle_mask)
overlap = intersection.sum() / 255
if overlap / space_area > 0.4:
return True
return False
Разметка машиномест
Первоначальная разметка зон машиномест выполняется один раз через веб-интерфейс:
class ParkingSpaceLabeler:
"""Интерактивная разметка машиномест на кадре"""
def __init__(self, image_path: str):
self.image = cv2.imread(image_path)
self.spaces = []
self.current_polygon = []
def interactive_label(self):
"""Запуск интерактивной разметки (для ручного использования)"""
cv2.namedWindow('Label Parking Spaces')
cv2.setMouseCallback('Label Parking Spaces', self._on_click)
while True:
display = self.image.copy()
for space in self.spaces:
cv2.polylines(display, [space['polygon']], True, (0, 255, 0), 2)
if self.current_polygon:
cv2.polylines(display,
[np.array(self.current_polygon)], False, (0, 0, 255), 2)
cv2.imshow('Label Parking Spaces', display)
key = cv2.waitKey(1)
if key == ord('s') and len(self.current_polygon) >= 4:
self.spaces.append({
'id': f'space_{len(self.spaces)+1}',
'polygon': self.current_polygon.copy()
})
self.current_polygon = []
elif key == ord('q'):
break
return self.spaces
Integration с системой навигации
- Digital signage: экраны с картой парковки, обновление в реальном времени
- Мобильное приложение: бронирование мест, навигация к свободному месту
- Умные светофоры: зелёный/красный индикатор над каждым рядом
- ANPR интеграция: автоматический въезд/выезд по номеру, расчёт стоимости
Metrics системы
| Параметр | Значение |
|---|---|
| Точность определения занятости | 96–99% |
| Latency обновления | < 5 секунд |
| Камер на 1 GPU | 8–16 (зависит от разрешения) |
| Машиномест на камеру | 10–50 (зависит от ракурса) |
| Ложные определения занятости | < 2% |
| Масштаб системы | Срок |
|---|---|
| 1–4 камеры, 50–200 мест | 3–4 недели |
| 10–20 камер, многоуровневая | 6–9 недель |
| Enterprise, навигация + API | 10–16 недель |







