Ищем свободное парковочное место с Python

Original author: Adam Geitgey
  • Translation
image

Я живу в хорошем городе. Но, как и во многих других, поиск парковочного места всегда превращается в испытание. Свободные места быстро занимают, и даже если у вас есть своё собственное, друзьям будет сложно к вам заехать, ведь им будет негде припарковаться.

Поэтому я решил направить камеру в окно и использовать глубокое обучение, чтобы мой компьютер сообщал мне, когда освободится место:

image

Это может звучать сложно, но на самом деле написать рабочий прототип с глубоким обучением — быстро и легко. Все нужные составляющие уже есть — нужно всего лишь знать, где их найти и как собрать воедино.

Поэтому давайте немного развлечёмся и напишем точную систему уведомлений о свободной парковке с помощью Python и глубокого обучения

Декомпозируем задачу


Когда у нас есть сложная задача, которую мы хотим решить с помощью машинного обучения, первым шагом нужно разбить её на последовательность простых задач. Затем мы можем использовать различные инструменты для решения каждой из них. Объединив несколько простых решений воедино, мы получим систему, которая способна на нечто сложное.

Вот, как я разбил свою задачу:

image

На вход конвейера поступает видеопоток с веб-камеры, направленной в окно:

image

Через конвейер мы будем передавать каждый кадр видео, по одному за раз.

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

Затем на каждом кадре нужно найти все машины. Это позволит нам отслеживать движение каждой машины от кадра к кадру.

Третьим шагом нужно определить, какие места заняты машинами, а какие — нет. Для этого нужно совместить результаты первых двух шагов.

Наконец, программа должна прислать оповещение, когда освободится парковочное место. Это будет определяться за счёт изменений в расположении машин между кадрами видео.

Каждый из этих этапов можно пройти разными способами с помощью разных технологий. Нет единственного правильного или неправильного способа составить этот конвейер, у разных подходов будут свои преимущества и недостатки. Давайте разберёмся с каждым шагом подробнее.

Распознаём парковочные места


Вот, что видит наша камера:

image

Нам нужно как-то просканировать это изображение и получить список мест, где можно припарковаться:

image

Решением «в лоб» было бы просто захардкодить местоположения всех парковочных мест вручную вместо автоматического распознавания. Но в таком случае, если мы переместим камеру или захотим искать парковочные места на другой улице, нам придётся проделывать всю процедуру заново. Звучит так себе, поэтому поищем автоматический способ распознавания парковочных мест.

Как вариант, можно искать на изображении паркометры и предположить, что рядом с каждым из них есть парковочное место:

image

Однако с этим подходом не всё так гладко. Во-первых, не у каждого парковочного места есть паркометр, да и вообще, нам больше интересен поиск парковочных мест, за которые не надо платить. Во-вторых, местоположение паркометра ничего не говорит нам о том, где находится парковочное место, а всего лишь позволяет сделать предположение.

Другая идея заключается в создании модели распознавания объектов, которая ищет метки парковочного места, нарисованные на дороге:

image

Но и этот подход — так себе. Во-первых, в моём городе все такие метки очень маленькие и трудноразличимые на расстоянии, поэтому их будет сложно обнаружить с помощью компьютера. Во-вторых, на улице полно всяких других линий и меток. Будет сложно отделить парковочные метки от разделителей полос и пешеходных переходов.

Когда вы сталкиваетесь с проблемой, которая на первый взгляд кажется сложной, потратьте несколько минут на поиск другого подхода к решению задачи, который поможет обойти некоторые технические проблемы. Что вообще есть парковочное место? Это всего лишь место, на которое на долгое время паркуют машину. Возможно, нам вовсе и не нужно распознавать парковочные места. Почему бы нам просто не распознавать машины, которые долгое время стоят на месте, и не делать предположение, что они стоят на парковочном месте?

Другими словами, парковочные места расположены там, где подолгу стоят машины:

image

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

Распознаём машины


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

  • Можно обучить детектор на основе HOG (Histogram of Oriented Gradients, гистограммы направленных градиентов) и пройтись им по всему изображению, чтобы найти все машины. Этот старый подход, не использующий глубокое обучение, работает относительно быстро, но не очень хорошо справляется с машинами, расположенными по-разному.
  • Можно обучить детектор на основе CNN (Convolutional Neural Network, свёрточная нейронная сеть) и пройтись им по всему изображению, пока не найдём все машины. Этот подход работает точно, но не так эффективно, так как нам нужно просканировать изображение несколько раз с помощью CNN, чтобы найти все машины. И хотя так мы сможем найти машины, расположенные по-разному, нам потребуется гораздо больше обучающих данных, чем для HOG-детектора.
  • Можно использовать новый подход с глубоким обучением вроде Mask R-CNN, Faster R-CNN или YOLO, который совмещает в себе точность CNN и набор технических хитростей, сильно повышающих скорость распознавания. Такие модели будут работать относительно быстро (на GPU), если у нас есть много данных для обучения модели.

В общем случае нам нужно самое простое решение, которое будет работать как надо и потребует наименьшее количество обучающих данных. Не обязательно, чтобы это был самый новый и быстрый алгоритм. Однако конкретно в нашем случае Mask R-CNN — разумный выбор, несмотря на то, что он довольно новый и быстрый.

Архитектура Mask R-CNN разработана таким образом, что она распознаёт объекты на всём изображении, эффективно тратя ресурсы, и при этом не использует подход скользящего окна. Другими словами, она работает довольно быстро. С современным GPU мы сможем распознавать объекты на видео в высоком разрешении на скорости в несколько кадров в секунду. Для нашего проекта этого должно быть достаточно.

Кроме того, Mask R-CNN даёт много информации о каждом распознанном объекте. Большинство алгоритмов распознавания возвращают только ограничивающую рамку для каждого объекта. Однако Mask R-CNN не только даст нам местоположение каждого объекта, но и его контур (маску):

image

Для обучения Mask R-CNN нам нужно много изображений объектов, которые мы хотим распознавать. Мы могли бы выйти на улицу, сфотографировать машины и обозначить их на фотографиях, что потребовало бы несколько дней работы. К счастью, машины — одни из тех объектов, которые люди часто хотят распознать, поэтому уже существуют несколько общедоступных датасетов с изображениями машин.

Один из них — популярный датасет СОСО(сокращение для Common Objects In Context), в котором есть изображения, аннотированные масками объектов. В этом датасете находится более 12 000 изображений с уже размеченными машинами. Вот пример изображения из датасета:

image

Такие данные отлично подходят для обучения модели на основе Mask R-CNN.

Но придержите коней, есть новости ещё лучше! Мы не первые, кому захотелось обучить свою модель с помощью датасета COCO — многие люди уже сделали это до нас и поделились своими результатами. Поэтому вместо обучения своей модели мы можем взять готовую, которая уже может распознавать машины. Для нашего проекта мы воспользуемся open-source моделью от Matterport.

Если дать на вход этой модели изображение с камеры, вот что мы получим уже «из коробки»:

image

Модель распознала не только машины, но и такие объекты, как светофоры и люди. Забавно, что дерево она распознала как комнатное растение.

Для каждого распознанного объекта модель Mask R-CNN возвращает 4 вещи:

  • Тип обнаруженного объекта (целое число). Предобученная модель COCO умеет распознавать 80 разных часто встречающихся объектов вроде машин и грузовиков. С их полным списком можно ознакомиться здесь.
  • Степень уверенности в результатах распознавания. Чем выше число, тем сильнее модель уверена в правильности распознавания объекта.
  • Ограничивающая рамка для объекта в форме XY-координат пикселей на изображении.
  • «Маска», которая показывает, какие пиксели внутри ограничивающей рамки являются частью объекта. С помощью данных маски можно найти контур объекта.

Ниже показан код на Python для обнаружения ограничивающей рамки для машин с помощью предобученной модели Mask R-CNN и OpenCV:

import numpy as np
import cv2
import mrcnn.config
import mrcnn.utils
from mrcnn.model import MaskRCNN
from pathlib import Path


# Конфигурация, которую будет использовать библиотека Mask-RCNN.
class MaskRCNNConfig(mrcnn.config.Config):
    NAME = "coco_pretrained_model_config"
    IMAGES_PER_GPU = 1
    GPU_COUNT = 1
    NUM_CLASSES = 1 + 80  # в датасете COCO находится 80 классов + 1 фоновый класс.
    DETECTION_MIN_CONFIDENCE = 0.6


# Фильтруем список результатов распознавания, чтобы остались только автомобили.
def get_car_boxes(boxes, class_ids):
    car_boxes = []

    for i, box in enumerate(boxes):
        # Если найденный объект не автомобиль, то пропускаем его.
        if class_ids[i] in [3, 8, 6]:
            car_boxes.append(box)

    return np.array(car_boxes)


# Корневая директория проекта.
ROOT_DIR = Path(".")

# Директория для сохранения логов и обученной модели.
MODEL_DIR = ROOT_DIR / "logs"

# Локальный путь к файлу с обученными весами.
COCO_MODEL_PATH = ROOT_DIR / "mask_rcnn_coco.h5"

# Загружаем датасет COCO при необходимости.
if not COCO_MODEL_PATH.exists():
    mrcnn.utils.download_trained_weights(COCO_MODEL_PATH)

# Директория с изображениями для обработки.
IMAGE_DIR = ROOT_DIR / "images"

# Видеофайл или камера для обработки — вставьте значение 0, если нужно использовать камеру, а не видеофайл.
VIDEO_SOURCE = "test_images/parking.mp4"

# Создаём модель Mask-RCNN в режиме вывода.
model = MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=MaskRCNNConfig())

# Загружаем предобученную модель.
model.load_weights(COCO_MODEL_PATH, by_name=True)

# Местоположение парковочных мест.
parked_car_boxes = None

# Загружаем видеофайл, для которого хотим запустить распознавание.
video_capture = cv2.VideoCapture(VIDEO_SOURCE)

# Проходимся в цикле по каждому кадру.
while video_capture.isOpened():
    success, frame = video_capture.read()
    if not success:
        break

    # Конвертируем изображение из цветовой модели BGR (используется OpenCV) в RGB.
    rgb_image = frame[:, :, ::-1]

    # Подаём изображение модели Mask R-CNN для получения результата.
    results = model.detect([rgb_image], verbose=0)

    # Mask R-CNN предполагает, что мы распознаём объекты на множественных изображениях.
    # Мы передали только одно изображение, поэтому извлекаем только первый результат.
    r = results[0]

    # Переменная r теперь содержит результаты распознавания:
    # - r['rois'] — ограничивающая рамка для каждого распознанного объекта;
    # - r['class_ids'] — идентификатор (тип) объекта;
    # - r['scores'] — степень уверенности;
    # - r['masks'] — маски объектов (что даёт вам их контур).

    # Фильтруем результат для получения рамок автомобилей.
    car_boxes = get_car_boxes(r['rois'], r['class_ids'])

    print("Cars found in frame of video:")

    # Отображаем каждую рамку на кадре.
    for box in car_boxes:
        print("Car:", box)

        y1, x1, y2, x2 = box

        # Рисуем рамку.
        cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 1)

    # Показываем кадр на экране.
    cv2.imshow('Video', frame)

    # Нажмите 'q', чтобы выйти.
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Очищаем всё после завершения.
video_capture.release()
cv2.destroyAllWindows()

После запуска этого скрипта на экране появится изображение с рамкой вокруг каждой обнаруженной машины:

image

Также в консоль будут выведены координаты каждой машины:

Cars found in frame of video:
Car: [492 871 551 961]
Car: [450 819 509 913]
Car: [411 774 470 856]

Вот мы и научились распознавать машины на изображении.

Распознаём пустые парковочные места


Мы знаем пиксельные координаты каждой машины. Просматривая несколько последовательных кадров, мы легко можем определить, какие из машин не двигались, и предположить, что там находятся парковочные места. Но как понять, что машина покинула парковку?

Проблема в том, что рамки машин частично перекрывают друг друга:

image

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

Мы воспользуемся мерой под названием Intersection Over Union (отношение площади пересечения к сумме площадей) или IoU. IoU можно найти, посчитав количество пикселей, где пересекаются два объекта, и разделить на количество пикселей, занимаемых этими объектами:

image

Так мы сможем понять, как сильно ограничивающая рамка машины пересекается с рамкой парковочного места. Это позволит легко определить, свободна ли парковка. Если значение IoU низкое, вроде 0.15, значит, машина занимает малую часть парковочного места. А если оно высокое, вроде 0.6, то это значит, что машина занимает большую часть места и там нельзя припарковаться.

Поскольку IoU используется довольно часто в компьютерном зрении, в соответствующих библиотеках с большой вероятностью есть реализация этой меры. В нашей библиотеке Mask R-CNN она реализована в виде функции mrcnn.utils.compute_overlaps().

Если у нас есть список ограничивающих рамок для парковочных мест, то добавить проверку на наличие машин в этих рамках можно, добавив всего строку-другую кода:

    # Фильтруем результат для получения рамок автомобилей.
    car_boxes = get_car_boxes(r['rois'], r['class_ids'])

    # Смотрим, как сильно машины пересекаются с известными парковочными местами.
    overlaps = mrcnn.utils.compute_overlaps(car_boxes, parking_areas)

    print(overlaps)

Результат должен выглядеть примерно так:

[
 [1.         0.07040032 0.         0.]
 [0.07040032 1.         0.07673165 0.]
 [0.         0.         0.02332112 0.]
]

В этом двумерном массиве каждая строка отражает одну рамку парковочного места. А каждый столбец говорит о том, насколько сильно каждое из мест пересекается с одной из обнаруженных машин. Результат 1.0 означает, что всё место полностью занято машиной, а низкое значение вроде 0.02 говорит о том, что машина немного влезла на место, но на нём ещё можно припарковаться.

Чтобы найти незанятые места, нужно всего лишь проверить каждую строку в этом массиве. Если все числа близки к нулю, то скорее всего место свободно!

Однако имейте в виду, что распознавание объектов не всегда работает идеально с видео в реальном времени. Хоть модель на основе Mask R-CNN довольно точна, время от времени она может пропустить машину-другую в одном кадре видео. Поэтому прежде чем утверждать, что место свободно, нужно убедиться, что оно остаётся таким ещё на протяжении 5–10 следующих кадров видео. Таким образом мы сможем избежать ситуаций, когда система ошибочно помечает место пустым из-за глюка на одном кадре видео. Как только мы убедимся, что место остаётся свободным в течение нескольких кадров, можно отсылать сообщение!

Отправляем SMS


Последняя часть нашего конвейера — отправка SMS-уведомления при появлении свободного парковочного места.

Отправить сообщение из Python очень легко, если использовать Twilio. Twilio — это популярный API, который позволяет отправлять SMS из практически любого языка программирования с помощью всего нескольких строк кода. Конечно, если вы предпочитаете другой сервис, то можете использовать и его. Я никак не связан с Twilio, просто это первое, что приходит на ум.

Чтобы использовать Twilio, зарегистрируйте пробный аккаунт, создайте номер телефона Twilio и получите аутентификационные данные аккаунта. Затем установите клиентскую библиотеку:

$ pip3 install twilio

После этого используйте следующий код для отправки сообщения:

from twilio.rest import Client

# Данные аккаунта Twilio.
twilio_account_sid = 'Ваш Twilio SID'
twilio_auth_token = 'Ваш токен аутентификации Twilio'
twilio_source_phone_number = 'Ваш номер телефона Twilio'

# Создаём объект клиента Twilio.
client = Client(twilio_account_sid, twilio_auth_token)

# Отправляем SMS.
message = client.messages.create(
    body="Тело сообщения",
    from_=twilio_source_phone_number,
    to="Ваш номер, куда придёт сообщение"
)

Чтобы добавить возможность отправки сообщений в наш скрипт, просто скопируйте туда этот код. Однако нужно сделать так, чтобы сообщение не отправлялось на каждом кадре, где видно свободное место. Поэтому у нас будет флаг, который в установленном состоянии не даст отправлять сообщения в течение какого-то времени или пока не освободится другое место.

Складываем всё воедино


import numpy as np
import cv2
import mrcnn.config
import mrcnn.utils
from mrcnn.model import MaskRCNN
from pathlib import Path
from twilio.rest import Client

# Конфигурация, которую будет использовать библиотека Mask-RCNN.
class MaskRCNNConfig(mrcnn.config.Config):
    NAME = "coco_pretrained_model_config"
    IMAGES_PER_GPU = 1
    GPU_COUNT = 1
    NUM_CLASSES = 1 + 80  # в датасете COCO находится 80 классов + 1 фоновый класс.
    DETECTION_MIN_CONFIDENCE = 0.6

# Фильтруем список результатов распознавания, чтобы остались только автомобили.
def get_car_boxes(boxes, class_ids):
    car_boxes = []

    for i, box in enumerate(boxes):
        # Если найденный объект не автомобиль, то пропускаем его.
        if class_ids[i] in [3, 8, 6]:
            car_boxes.append(box)

    return np.array(car_boxes)

# Конфигурация Twilio.
twilio_account_sid = 'Ваш Twilio SID'
twilio_auth_token = 'Ваш токен аутентификации Twilio'
twilio_phone_number = 'Ваш номер телефона Twilio'
destination_phone_number = 'Номер, куда придёт сообщение'
client = Client(twilio_account_sid, twilio_auth_token)

# Корневая директория проекта.
ROOT_DIR = Path(".")

# Директория для сохранения логов и обученной модели.
MODEL_DIR = ROOT_DIR / "logs"

# Локальный путь к файлу с обученными весами.
COCO_MODEL_PATH = ROOT_DIR / "mask_rcnn_coco.h5"

# Загружаем датасет COCO при необходимости.
if not COCO_MODEL_PATH.exists():
    mrcnn.utils.download_trained_weights(COCO_MODEL_PATH)

# Директория с изображениями для обработки.
IMAGE_DIR = ROOT_DIR / "images"

# Видеофайл или камера для обработки — вставьте значение 0, если использовать камеру, а не видеофайл.
VIDEO_SOURCE = "test_images/parking.mp4"

# Создаём модель Mask-RCNN в режиме вывода.
model = MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=MaskRCNNConfig())

# Загружаем предобученную модель.
model.load_weights(COCO_MODEL_PATH, by_name=True)

# Местоположение парковочных мест.
parked_car_boxes = None

# Загружаем видеофайл, для которого хотим запустить распознавание.
video_capture = cv2.VideoCapture(VIDEO_SOURCE)

# Сколько кадров подряд с пустым местом мы уже видели.
free_space_frames = 0

# Мы уже отправляли SMS?
sms_sent = False

# Проходимся в цикле по каждому кадру.
while video_capture.isOpened():
    success, frame = video_capture.read()
    if not success:
        break

    # Конвертируем изображение из цветовой модели BGR в RGB.
    rgb_image = frame[:, :, ::-1]

    # Подаём изображение модели Mask R-CNN для получения результата.
    results = model.detect([rgb_image], verbose=0)

    # Mask R-CNN предполагает, что мы распознаём объекты на множественных изображениях.
    # Мы передали только одно изображение, поэтому извлекаем только первый результат.
    r = results[0]

    # Переменная r теперь содержит результаты распознавания:
    # - r['rois'] — ограничивающая рамка для каждого распознанного объекта;
    # - r['class_ids'] — идентификатор (тип) объекта;
    # - r['scores'] — степень уверенности;
    # - r['masks'] — маски объектов (что даёт вам их контур).

    if parked_car_boxes is None:
        # Это первый кадр видео — допустим, что все обнаруженные машины стоят на парковке.
        # Сохраняем местоположение каждой машины как парковочное место и переходим к следующему кадру.
        parked_car_boxes = get_car_boxes(r['rois'], r['class_ids'])
    else:
        # Мы уже знаем, где места. Проверяем, есть ли свободные.

        # Ищем машины на текущем кадре.
        car_boxes = get_car_boxes(r['rois'], r['class_ids'])

        # Смотрим, как сильно эти машины пересекаются с известными парковочными местами.
        overlaps = mrcnn.utils.compute_overlaps(parked_car_boxes, car_boxes)

        # Предполагаем, что свободных мест нет, пока не найдём хотя бы одно.
        free_space = False

        # Проходимся в цикле по каждому известному парковочному месту.
        for parking_area, overlap_areas in zip(parked_car_boxes, overlaps):

            # Ищем максимальное значение пересечения с любой обнаруженной
            # на кадре машиной (неважно, какой).
            max_IoU_overlap = np.max(overlap_areas)

            # Получаем верхнюю левую и нижнюю правую координаты парковочного места.
            y1, x1, y2, x2 = parking_area

            # Проверяем, свободно ли место, проверив значение IoU.
            if max_IoU_overlap < 0.15:
                # Место свободно! Рисуем зелёную рамку вокруг него.
                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 3)
                # Отмечаем, что мы нашли как минимум оно свободное место.
                free_space = True
            else:
                # Место всё ещё занято — рисуем красную рамку.
                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 1)

            # Записываем значение IoU внутри рамки.
            font = cv2.FONT_HERSHEY_DUPLEX
            cv2.putText(frame, f"{max_IoU_overlap:0.2}", (x1 + 6, y2 - 6), font, 0.3, (255, 255, 255))

        # Если хотя бы одно место было свободным, начинаем считать кадры.
        # Это для того, чтобы убедиться, что место действительно свободно
        # и не отправить лишний раз уведомление.
        if free_space:
            free_space_frames += 1
        else:
            # Если всё занято, обнуляем счётчик.
            free_space_frames = 0

        # Если место свободно на протяжении нескольких кадров, можно сказать, что оно свободно.
        if free_space_frames > 10:
            # Отображаем надпись SPACE AVAILABLE!! вверху экрана.
            font = cv2.FONT_HERSHEY_DUPLEX
            cv2.putText(frame, f"SPACE AVAILABLE!", (10, 150), font, 3.0, (0, 255, 0), 2, cv2.FILLED)

            # Отправляем сообщение, если ещё не сделали это.
            if not sms_sent:
                print("SENDING SMS!!!")
                message = client.messages.create(
                    body="Parking space open - go go go!",
                    from_=twilio_phone_number,
                    to=destination_phone_number
                )
                sms_sent = True

        # Показываем кадр на экране.
        cv2.imshow('Video', frame)

    # Нажмите 'q', чтобы выйти.
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Нажмите 'q', чтобы выйти.
video_capture.release()
cv2.destroyAllWindows()

Для запуска того кода сначала нужно установить Python 3.6+, Matterport Mask R-CNN и OpenCV.

Я специально писал код как можно проще. Например, если он видит на первом кадре машины, то делает вывод, что все они припаркованы. Попробуйте поэкспериментировать с ним и посмотрите, получится ли у вас повысить его надёжность.

Просто изменив идентификаторы объектов, которые ищет модель, вы можете превратить код в нечто совершенно иное. Например, представьте, что вы работаете на горнолыжном курорте. Внеся пару изменений, вы можете превратить этот скрипт в систему, которая автоматически распознаёт сноубордистов, спрыгивающих с рампы, и записывает ролики с классными прыжками. Или, если вы работаете в заповеднике, вы можете создать систему, которая считает зебр. Вы ограничены лишь своим воображением.

Больше подобных статей можно читать в телеграм-канале Нейрон (@neurondata)

Ссылка на альтернативный перевод: tproger.ru/translations/parking-searching/

Всем знаний. Экспериментируйте!

Only registered users can participate in poll. Log in, please.

А что бы вы хотели распознавать и отслеживать?

Support the author
Share post

Similar posts

Comments 51

    +17
    А мужик, который будет говорить: «Я тут двадцать лет ставлю», в программе учитывается?
      +5
      Конечно — отсылается СМС в полицию
        +1
        Лично у нас во дворе я очень сомневаюсь, что кто-то что-то говорить будет, в 99% сразу по фейсу дадут.
        В таком случае, не мешало бы прогу научить и в скорую СМС отправлять…
          +1

          … зато люди у нас хорошие.


          УК РФ Статья 213. Хулиганство наказывается штрафом в размере от пятисот тысяч до одного миллиона рублей или в размере заработной платы или иного дохода осужденного за период от трех до четырех лет, либо принудительными работами на срок до пяти лет, либо лишением свободы на срок до семи лет.

          Системы распознавания агрессивного поведения на улице, кстати, тоже существуют.

            0
            Это у вас в Москве такие порядки, камеры стоят на каждом шагу, а у нас в глубинках без проблем ездят на красный свет по пешеходному переходу, да половина вообще без прав катается…
            А что касается парковок, то человеку даже трудно объяснить, чтобы он поставил машину не как ему хочется, а чтобы другие тоже могли припарковаться. Тупо кидают машину, как хотят, а чуть что начинаешь пылить, сразу кулаками машут…
            Жаль, но везде еще «путинский рай» наступил, страна то огромная…
        +3
        А мужик, который будет говорить: «Я тут двадцать лет ставлю»

        В США это не работает. Есть 2 варианта — публичная парковка (как в данном случае) и парковка для определённого владельца. Обычно, всегда понятно публичная парковка или нет. Вдоль дороги парковки всегда публичные и работает правило — кто первый тот и занял. Понятие очереди в США — «святое» вне зависимости от того кто, где и сколько ставил до этого и кто это такой — хоть мэр — все в одну линию (все равны).
        +3
        Pathlib — прекрасная вещь, о которой я раньше не знал. Спасибо.
          +2
          Очень интересная и познавательная статья! Спасибо!
          Правда, возникает вопрос о надёжности в дождь/снег/туман + ложные срабатывания на машины экстренных служб (которые паркуются по другим правилам).
            +6
            В голосовалке про комаров и правда интересно, если это не шутка, т.к. давно грежу созданием девайса по уничтожению комаров: распознавание кровососущих, захват цели, наведение маломощного лазера, огонь. Даже условия продумывал: чтобы все это выше уровня кровати с находящимися в ней людьми, для минимизации рисков и с отменой «огня» если на дистанции люди или питомцы (по этому и их распознавание тоже становится нужно). Этакий маленький домашний лазерный пэтриот =)
            +3
            Классная статья! Побольше бы таких!
              +3
              Очень похоже на tproger.ru/translations/parking-searching
                0

                И не просто похоже, а оно и есть. Вот только почему здесь переводчик другой?

                  0
                  А как модераторам хабра написать? Копирайт перевода нарушен («переводчик» местами слегка изменил формулировки оригинального перевода), добавлена реклама своего канала.
                  –1
                  спасибо! Я уж было подписался на канал.
                  Теперь хаброэффект должен сработать обратно — все приличные люди должны отписаться. По идее. Если нейронки на совесть обучены в детстве :)
                  0
                  Интересно, а есть алгоритм обнаружения забытых вещей с поиском хозяина.
                    +1
                    Отличная статья написанная понятным языком даже для человека, который с программированием никак не связан (как например я)! Присоединяюсь к другим комментаторам, что надо больше таких.

                    Вопрос: а если бы мы в ручную фотографировали, то как бы выглядело обучение этой системы? Нам надо было обводить контур каждой машины на определённом количестве фотографий? (Только сейчас заметил, что это перевод. Но может кто из местных знает.)
                      +1
                      да, вручную, титанический труд (так как нужно тысячи и десятки тысяч изображений).

                      Есть отличная альтернатива (на хабре даже упоминалась) — использование компьютерных игр типа gta, в которых реализован симулятор города, машин, людей, светофоров и прочего прочего. Т.е. вы с помощью расширения к игре получаете информацию о содержимом кадра с попиксельной точностью (т.е. не прямоугольная область, а круче — каждый пиксел на изображении) и даже можете строить свои сцены (расположение объектов и камеры).

                      Можно понизить качество изображения, с помощью фильтров, добавив помехи, погоду и искажения, вносимые камерами с низкой скоростью сенсоров (когда при движении изображение идет волнами). И получить огромный датасет, практически любого размера, ограниченный возможностями вашего кошелька для обучения.
                      +1

                      Как работает в темное время суток?

                        0
                        Плохо. Проверено
                        0
                        К примеру, как быть с ситуацией, если свободное парковочное место не подходит по габаритам. Один товарищ умеет в сантиметр уместиться, а кому-то нужно существенно больше?
                          0

                          Думаю, если машины стоят плотно, то это отразится на IoU мере — получится, что место освободилось как бы не полностью. Скажем, стало не меньше 0.02, а 0.05. Тогда можно будет подобрать такое пороговое значение, чтобы четко обнаруживать достаточно свободные места. Но, конечно, тут лучше проверить экспериментально.


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


                          Результат 1.0 означает, что всё место полностью занято машиной, а низкое значение вроде 0.02 говорит о том, что машина немного влезла на место, но на нём ещё можно припарковаться.
                          –8
                          Извиняюсь, что не совсем по теме, но у в Вашем доме не предусмотрена гостевая парковка?
                            0

                            Я вам так скажу, в моём комплексе предусмотрена гостевая парковка, но она под завязку забита машинами жильцов. Потому что паркингов крайне мало (вроде планируются ещё), а машин крайне много. И от того, что одна парковка называется гостевой, а другая — нет — ничего глобально не меняется.
                            P.S. А ещё гостевая парковка под подъездом, а до паркинга надо топать. Очевидно, что большинство старается припарковаться поближе.

                            +1
                            Мои 5 центов: статья действительно неплохая, и любопытный результат достигнут буквально «на коленках» (но тут заслуга «стояния на плечах титанов», конечно). Но, по-моему, из восторгающихся, мало кто заметил, что это… очередной перевод. Вообще, из интересных и не «флеймовых» статей (о страданиях начинающих программистах, уродах-интервьюерах и т.п.), в последнее время на хабре одни лишь переводы, даже в такой традиционной области, как DIY.

                            С практической же точки зрения, просто непонятно, для чего подобная система нужна. Сообщать владельцу, есть-ли свободная парковка у дома? Просто бессмысленно: в больших городах, с проблемными парковочными местами, даже если чудом парковка освободится, то ее, с очень высокой вероятностью, займут через 1 минуту, не успеешь доехать. Поэтому, как правило, жители подобных «проблемных» (как правило, довольно дорогих и богатых) мест вынуждены платить очень серьезные суммы (чтобы не сказать, фантастические) за выделенную парковку.
                              +1
                              Подобная система нужна скорее для демонстрации возможностей современных библиотек, чем для решения реальных проблем с парковкой. В статье упоминается о том, что этот скрипт можно применять для решения похожих задач, в этом наверное и есть его главная ценность. Перевод качественный, спасибо и автору и переводчику. А Вам, кстати, никто не мешает написать хорошую статью про отечественные нейросети.
                                0
                                «Отечественные нейросети» для меня будут, как раз, американские, но я сейчас ими не занимаюсь, поэтому разумную статью написать не могу. В свою очередь, хочу вас спросить: собирали-ли и пробовали-ли вы OpenCV examples? Там удивительного чуть ли не больше, чем в данной статье. А статья неплохая, я это написал, только пример выбран не очень удачный; думаю, для демонстрации можно было придумать и более жизненный (правда, какой именно, я сам не знаю. Распознавание лиц гостей, звонящих/стучащих в дверь? Возможно, более жизненно, но не уверен).
                                  0
                                  Отечественные сети это конечно сарказм, имхо у науки не должно быть национальности. Примеры посмотрел, спасибо.
                                –2

                                Только это не перевод, это слегка исправленная копипаста перевода с рекламой своего телеграмм-канала.

                                  0

                                  Локально — конечно это не решение проблемы (с парковкой). Глобально (как учёт парковочных мест) — вполне себе.
                                  Представьте, что вы едете по городу, нужно припарковаться, но вы знаете что вот тут за углом ближе, но шансов крайне мало. А если там нет, но уже свернули, то нужно будет пару кругов намотать в поисках места. Или поехать сразу чуть дальше, но 90% что там место будет.
                                  Так, если сделать приложение, которое точно скажет что место есть (и оно, например, не забронировано 5-тиминутной бронью), вы сразу поедете на место. Просто как пример.
                                  А ещё проще — исправить счётчик многоуровневых парковок в ТЦ — там стоит тупой счётчик въезда-выезда, а где то самое свободное место — ищите. А пока ищете, на счётчике уже будет -10, потому что въехавших больше, чем выехавших.

                                    0
                                    Использование камеры с нейросетью, требующей мощного CPU, это слишком большой overhead для такой задачи. Решаться подобное должно путем копеечных датчиков на smart parking meters, и WiFi-связи с центральным сервером. Когда-то читал, что в каких-то городах Штатов уже проводятся подобные эксперименты, но линк привести не могу, к сожалению.
                                      0
                                      Решаться подобное должно путем копеечных датчиков на smart parking meters

                                      Кстати, напомнило, что видел что-то такое в одном из БЦ — там лампочки над паркоместами светились красным/зелёным в зависимости от занятости места. Полагаю, не просто светятся, но и инфу куда-то пишут. Для закрытых паркингов да, это должно быть дешевле.

                                        0
                                        Я фигню написал: у smart meters уже есть связь (кредитки-то они принимают)! В Бостоне и окрестностях сейчас активно меняют старые митеры на новые, «умные». Думаю, что и датчики там уже есть, равно, как и сбор данных об использовании — для внутренних целей пока, для облегчения жизни «шакалов» из городских парковочных служб (тикеты за парковку выписывают пока еще вручную).

                                        Imho, дело только в гейтвее/сервисе и клиентском приложении. Надеюсь, что скоро появятся (хотя для меня эта проблема остро и не стоит, а несколько раз в месяц, когда мы выбираемся в даунтаун Бостона, можно и за гараж заплатить — благо, через онлайн это можно сделать за половину или даже четверть «оффлайновой» цены).
                                    +1
                                    Я бы обучал на курильщиках, которые бычки бросают на улицу и на собаководах, которые не убирают за своими собаками. Сразу с записью инцидента и отправкой куда следует.

                                    p.s. Сверните большие куски кода под кат, будет проще читать.
                                      +1
                                      Спасибо за статью. Но, насколько я понял, этот скрипт будет сообщать о появлении парковочного места в файле с видеозаписью, так? А как завернуть на него стриминговое видео с камеры? Иначе отсылка СМС как-то бессмысленна…
                                        0
                                        Upd: перечитал, нашел, где файл заменяется на камеру. Но все равно непонятно: предполагается, что это будет бесконечный цикл, который будет оценивать кадр за кадром?
                                        +1
                                        парковочные места расположены там, где подолгу стоят машины

                                        И тут, внезапно, пробка или авария и система сойдёт с ума.
                                          +1
                                          Интересны ресурсы под такой проект
                                          Наприме запустил на 4х летнем x1 lenovo (I5 8gb) на небольшом видео — почти сразу показал первый кадр, а потом система подвисла и уже минут 10 ничего не происходит, только вентилятор гудит
                                            0
                                            Ресурсы нужны такие, что я от оказался от этого способа. Не рентабельно получается. Можно добавить и купить себе парковочное место. окупится в моем случае за 4 года
                                              –3

                                              Можно тоже самое, но для поиска свободной девушки?

                                                0

                                                То есть подразумевается, что все встают строго на место, никто не занимает два места и никто не оставляет километр до ближайших машин?

                                                  +2

                                                  Замечательная обучающая статья. Особый респект автору за чистый код.

                                                    0
                                                    Вопрос в тему. Предположим, есть тысяча фотографий некоего животного или насекомого, возьмём для примера тукана, с его характерным клювом, и хочеться чтобы система, обучившись на этих фотографиях могла просмотреть миллионы других фотографий и отобрать те из них, где этот самый тукан (или что-то ещё, на чём обучались) тоже есть. Есть или пример такого кода, или даже готовое средство для такой задачи?
                                                      0
                                                      вам же в статье прямым текстом код готовый дали
                                                        +1
                                                        Вы уверены?
                                                        0
                                                        Да, для насекомых было бы особенно интересно, там часто есть возможность использовать правильно ориентированное фото расправленного насекомого, но мелкие детали или пропорции сложно распознаются глазом и долго листать по «goto» определителя.
                                                        0
                                                        Точно так. Но датасет для обучения подготовить и провести обучение придется самому
                                                          +2
                                                          Я просто не паркуюсь вот и все, езжу только рано утром по выходным. Я и саму городскую езду ненавижу, а был бы трек гоночный — не уходил бы с него днями. На работу на — табу, да и просто глупо, не удобно, медленно, да и вред окружающей среде. Тем более на метро всего 15 минут до моего офиса в центре москвы.

                                                          Only users with full accounts can post comments. Log in, please.