Приложение CNN, обнаруживающее внешние повреждения автомобиля (полный реализуемый код)

Последние достижения в области глубокого обучения и вычислительной инфраструктуры (облако, графические процессоры и т. Д.) Сделали рывок вперед в приложениях компьютерного зрения: от открывания двери в офис лицом к лицу до беспилотных автомобилей. Не так давно задача классификации изображений, такая как распознавание рукописных цифр (отличный набор данных MNIST) или идентификация базового объекта (кошка / собака), считалась большим успехом в области компьютерного зрения. Однако сверточные нейронные сети (CNN), являющиеся движущей силой приложений компьютерного зрения, быстро развиваются с появлением передовых и инновационных архитектур для решения практически любых проблем, связанных с визуальной системой под солнцем.

Автоматическое обнаружение внешних повреждений автомобиля и последующая их количественная оценка (серьезность повреждений) поможет дилерам подержанных автомобилей (торговая площадка) точно и быстро оценивать автомобили за счет исключения ручного процесса оценки повреждений. Эта концепция одинаково выгодна для страховщиков имущества и от несчастных случаев (P&C) с точки зрения более быстрого урегулирования претензий и, следовательно, большей удовлетворенности клиентов. В этой статье я шаг за шагом опишу концепцию обнаружения автомобильных царапин (наиболее частое внешнее повреждение) с использованием обучения передачи CNN с использованием бэкэнда Tensorflow.

Обнаружение повреждений автомобиля - типичное применение сегментации экземпляров

Прежде чем перейти к деталям бизнес-проблемы и шагов по ее реализации, я расскажу о технике, использованной в этом специальном приложении для обнаружения объектов, и ее обосновании. Как и большинство реальных проблем компьютерного зрения, здесь мы также будем использовать переносное обучение из подходящей предварительно обученной CNN, чтобы сэкономить огромное время при переподготовке всей матрицы весов. В качестве типичного приложения в технике обнаружения объектов у нас есть несколько вариантов выбора методов - R-CNN, Fast R-CNN, Faster R-CNN, SSD и т. Д. Чтобы получить обзор этих методов, я рекомендую прочитать эту статью . Вкратце, как и любая задача по обнаружению объектов, здесь также есть 3 следующие подзадачи:

A) Извлечение областей интереса (ROI): изображение передается в ConvNet, которая возвращает область интересов на основе таких методов, как выборочный поиск (RCNN) или RPN (региональное предложение N / W для более быстрого RCNN), а затем уровень объединения ROI на извлекли ROI, чтобы убедиться, что все регионы имеют одинаковый размер.

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

C) Задача регрессии: наконец, регрессия ограничивающего прямоугольника (BB) используется для прогнозирования ограничивающих прямоугольников для каждой идентифицированной области для сужения ограничивающих прямоугольников (получение точных BB, определяющих относительные координаты).

Однако в нашем случае недостаточно получить только BB квадратной / прямоугольной формы, поскольку царапины / повреждения автомобиля являются аморфными (без четко определенной формы или формы). Нам необходимо определить точные пиксели в ограничивающей рамке, которые соответствуют классу (повреждение ). Точное расположение царапины в пикселях только поможет определить местоположение и точно оценить ущерб. Поэтому нам нужно добавить еще одну пошаговую семантическую сегментацию (пиксельное затенение интересующего класса) во весь конвейер, для которого мы будем использовать архитектуру CNN (Mask R-CNN) на основе области маскировки.

Маска R-CNN:

Mask R-CNN - это модель сегментации экземпляра, которая позволяет идентифицировать попиксельное разграничение для интересующего нас класса объектов. Таким образом, Mask R-CNN имеет две широкие задачи: 1) обнаружение объектов на основе BB (также называемое задачей локализации) и 2) семантическая сегментация, которая позволяет сегментировать отдельные объекты в пикселях в пределах сцены, независимо от формы. Объедините эти две задачи. Маска R-CNN действительно получает сегментацию экземпляра для данного изображения.

Хотя подробное обсуждение Mask R-CNN выходит за рамки этой статьи, давайте рассмотрим основные компоненты и сделаем обзор различных потерь.

Компоненты Mask R-CNN (Источник)

Таким образом, по сути, маска R-CNN состоит из двух компонентов: 1) обнаружение объекта BB и 2) задача семантической сегментации. Для задачи обнаружения объекта используется архитектура, аналогичная Faster R-CNN. Единственная разница в Mask R-CNN - это шаг ROI. При использовании объединения ROI он использует выравнивание ROI, чтобы позволить пиксель-пиксель сохранить ROI и предотвратить потерю информации. Для задачи семантической сегментации он использует полностью сверточный n / w (FCN). FCN создает маски (в нашем случае это двоичные маски) вокруг объектов BB, создавая пиксельную классификацию каждой области (отдельный интересующий объект). Таким образом, в общей маске R-CNN минимизирует общие потери, состоящие из следующих потерь на каждой фазе сегментации экземпляра. Прежде чем перейти к другому определению потерь, давайте введем важные обозначения.

1) rpn_class_loss: потеря классификатора привязки RPN рассчитывается для каждой области интереса, а затем суммируется для всех областей интереса для одного изображения, а сеть rpn_class_loss будет суммировать rpn_class_loss для всех изображений (поезд / проверка). Так что это не что иное, как потеря кросс-энтропии.

2) rpn_bbox_loss: Потери регрессии сетевого RPN BB суммируются как rpn_class_loss. Значения потерь ограничивающего прямоугольника отражают расстояние между истинными параметрами бокса, то есть координатами (x, y) местоположения бокса, его шириной и высотой - и предсказанные. Это по своей природе потеря регрессии, и она наказывает большие абсолютные различия (приблизительно экспоненциально для более низких различий и линейно для более крупных различий.

Учитывая изображение, эта фаза RPN извлекает множество предложений восходящих областей вероятных местоположений объектов на изображении, а затем подавляет предложения областей с критериями ≥ 0,5 IoU (пересечение по объединению) и вычисляет rpn_class_loss (измерение правильности этих уточненных областей) и насколько они точны (rpn_bbox_loss). Метод точного вычисления потерь требует немного сложного нелинейного преобразования между центрами (предсказанные и наземные истины) и между шириной (предсказанные и наземные истины) и высотами (предсказанные и наземные истины). Точно сеть сокращает SSE между предсказанными координатами BB: (tx, ty, th, tw) - расположение предлагаемой области относительно цели: (Vx, Vy, Vh, Vw) - Названия истинных меток для региона. Таким образом, после включения функции гладких потерь L1 для класса u и для прогнозируемого ограничивающего прямоугольника t, rpn_bbox_loss будет:

Таким образом, на этапе RPN общая потеря сети составляет:

3) mrcnn_class_loss: принцип вычисления этой потери такой же, как и rpn_class_loss, однако это потеря классификации на этапе полностью сверточного n / w (FCN) во время пиксельной классификации для задачи семантической сегментации.

4) mrcnn_bbox_loss: Принцип вычисления этой потери такой же, как и для rpn_bbox_loss, однако это потеря регрессии BB на этапе полностью сверточного n / w (FCN) во время уточнения ограничивающей рамки маски R-CNN для задачи семантической сегментации.

5) mrcnn_mask_loss: это двоичная кросс-энтропийная потеря для головы маски во время маскировки точного местоположения объекта (аморфные внешние места повреждения автомобиля). Она наказывает неправильную попиксельную двоичную классификацию - передний план (пиксели повреждения) / фон (пиксели кузова автомобиля) ) относительно истинных меток классов.

В то время как первые потери генерируются на этапе обнаружения объекта BB, последние три потери генерируются во время задачи семантической сегментации. Таким образом, во время обучения сеть сводит к минимуму общие потери, состоящие из 5 компонентов (для каждого поезда и проверки).

Бизнес-проблема

В подержанных автомобилях (как на торговых площадках, так и у дилеров), помимо функциональности и наличия оборудования, а также состояния здоровья, которое можно получить только с помощью тест-драйва / ручного осмотра, наблюдаются внешние повреждения кузова автомобиля (царапины, вмятины, перекраска и т. Д.) жизненно важная роль в определении точной цены на автомобиль. В большинстве случаев эти повреждения обнаруживаются и оцениваются вручную по изображениям автомобиля в процессе оценки автомобиля. Тем не менее, новейшие системы компьютерного зрения могут определять место повреждения на кузове автомобиля и помогать ценообразованию количественно оценить ущерб без особого ручного вмешательства. Эта концепция также поможет автостраховщикам автоматически оценивать ущерб и быстрее обрабатывать претензии.

В следующем разделе я кратко рассмотрю подготовку данных и реализацию этой концепции на реальных изображениях автомобилей с использованием Mask R-CNN. Подробный код вместе со всеми входами (видео контента и изображение стиля) и выходом (сгенерированные кадры изображений) можно найти здесь в моем репозитории GitHub.

Шаг 1: Сбор данных - хотя мы будем использовать переносное обучение из подходящей предварительно обученной (весовой) архитектуры CNN, нам необходимо настроить сеть для нашего конкретного использования, чтобы минимизировать потери, специфичные для приложения - потери из-за несоответствия местоположения повреждения на уровне пикселей между землей правда и предсказано. Итак, мы запустим поезд n / w на использование 56 изображений повреждений вагонов, собранных из Google, из которых 49 изображений используются для поезда, а 7 используются для целей проверки.

Шаг 2: аннотации данных - поскольку концепция попадает в режим контролируемого обучения, нам необходимо маркировать данные. В контексте обнаружения объектов компьютерного зрения или локализации объекта такая маркировка называется аннотацией. Именно для нашего приложения он определяет области повреждения на изображении и точно отмечает их по границе царапины. Для целей аннотации я использовал аннотатор изображений VGG (VIA) по этой ссылке. Используя этот инструмент, я загрузил все свои изображения и нарисовал многоугольные маски вдоль границы повреждения для каждого изображения следующим образом.

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

Шаг 3: Настройка среды - это один из важных шагов перед обучением модели на собранных изображениях и аннотациях (этикетках), так как я буду использовать репозиторий Matterport Mask R-CNN для использования нескольких предварительно обученных CNN n. / w весовых матриц, построенных на различных стандартных наборах данных, таких как набор данных COCO, ImageNet и т. д., и пользовательских функциях, таких как обработка и подготовка данных, настройка конфигурации, обучение модели, создание файла журнала для сохранения итерационных объектов матрицы весов и н / б потери, обнаружение объектов, маскирование обнаруженных локализованных областей и т. д. Чтобы запустить пользовательскую функцию обучения для изображений и аннотаций, нам нужно сначала клонировать репозиторий, следуя точной структуре файлов и папок, как описано в репозитории. Эта маска Matterport R-CNN построена на основе API обнаружения объектов Tensorflow. Ниже приведены шаги перед началом тренировочного процесса.

а) Хранить обучающие и проверочные изображения и соответствующие файлы аннотаций в отдельных подпапках с именами «train» и «val» внутри папки данных. Я назвал это «обычай».

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

class CustomConfig(Config):
    """Configuration for training on the toy  dataset.
    Derives from the base Config class and overrides some values.
    """
    # Give the configuration a recognizable name
    NAME = "scratch"
    # We use a GPU with 6GB memory, which can fit only one image.
    # Adjust down if you use a smaller GPU.
    IMAGES_PER_GPU = 1
    # Number of classes (including background)
    NUM_CLASSES = 1 + 1  # Car Background + scratch
    # Number of training steps per epoch
    STEPS_PER_EPOCH = 100
    # Skip detections with < 90% confidence
    DETECTION_MIN_CONFIDENCE = 0.9

c) Наконец, нам нужно выбрать начальную точку - объект предварительно обученной матрицы весов, чтобы начать процесс обучения. Я выбрал mask_rcnn_coco.h5, который предварительно обучен на наборе данных coco.

Шаг 4: Загрузка наборов данных: здесь мы загружаем обучающие и проверочные изображения и помечаем отдельное изображение соответствующими метками или аннотациями. Здесь я настроил код baloon.py, написанный для Mask R-CNN в соответствии с приложением (метка класса, путь к каталогу, стандартизация форм и т. Д.), Чтобы подготовить custom_1.py, который загружает изображения и аннотации и добавляет их в класс CustomDataset. Код находится в моем репозитории GitHub.

class CustomDataset(utils.Dataset):
    def load_custom(self, dataset_dir, subset):
        """Load a subset of the dataset.
        dataset_dir: Root directory of the dataset.
        subset: Subset to load: train or val
        """
        # Add classes. We have only one class to add.
        self.add_class("scratch", 1, "scratch")

        # Train or validation dataset?
        assert subset in ["train", "val"]
        dataset_dir = os.path.join(dataset_dir + subset)

Шаг 4: Обучение сети. Теперь нам нужно усовершенствовать базу «mask_rcnn_coco.h5» с помощью обучения модели на реальных изображениях, и после каждой итерации (эпохи) обновленная матрица весов сохраняется в «журнале». Кроме того, статистика потерь по итерациям / эпохам сохраняется для мониторинга в TensorBoard.

def train(model):
    """Train the model."""
    # Training dataset.
    dataset_train = CustomDataset()
    dataset_train.load_custom(args.dataset, "train")
    dataset_train.prepare()
    # Validation dataset
    dataset_val = CustomDataset()
    dataset_val.load_custom(args.dataset, "val")
    dataset_val.prepare()
    # *** This training schedule is an example. Update to your needs ***
    # Since we're using a very small dataset, and starting from
    # COCO trained weights, we don't need to train too long. Also,
    # no need to train all layers, just the heads/last few layers should do it.
    print("Training network heads")
    model.train(dataset_train,dataset_val,
                learning_rate=config.LEARNING_RATE,epochs=15,layers='heads')
                layers='hea

Нам нужно запустить обучающий код (файл .py) на изображениях с помощью следующих команд

### Train the base model using pre-trained COCO weights(I ran using these weights,Download 'mask_rcnn_coco.h5' weights before starting the training)
py custom_1.py train --dataset=C:/Users/Sourish/Mask_RCNN/custom --weights=coco
### Train the base model using pre-trained imagenet weights(for this to download imagenet weights))
py custom_1.py train --dataset=C:/Users/Sourish/Mask_RCNN/custom --weights=imagenet
## We can even resume from the latest saved callback(latest saved weights)
python3 custom.py train --dataset=C:/Users/Sourish/Mask_RCNN/custom --weights=last

и начинается волшебство.

Шаг 4: Проверка модели - По мере каждой итерации (эпохи) обновленная матрица весов сохраняется в журнале. Также статистика потерь по итерациям / эпохам сохраняется для мониторинга в TensorBoard.

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

Шаг 5: Прогнозирование модели - после удовлетворительного и желательного мониторинга потерь - в идеале монотонно уменьшая потери как при обучении, так и при проверке, мы можем протестировать объект модели на случайно выбранных проверочных изображениях, чтобы увидеть точность прогноза (маскирование повреждений автомобиля).

image_id = random.choice(dataset.image_ids) #select a random image from validation dataset
image, image_meta, gt_class_id, gt_bbox, gt_mask =\
modellib.load_image_gt(dataset, config, image_id, use_mini_mask=False) #image loading
# Run object detection
results = model.detect([image], verbose=1)
# Display results
ax = get_ax(1)
r = results[0]
visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
                            dataset.class_names, r['scores'], ax=ax,
                            title="Predictions")
log("gt_class_id", gt_class_id)
log("gt_bbox", gt_bbox)
log("gt_mask", gt_mask)
#Showing damage polygon on car body
print('The car has:{} damages'.format(len(dataset.image_info[image_id]['polygons'])))

и вот прогноз.

И прогноз выглядит неплохо.

Внедрение бизнеса и перспективы на будущее

Продавцы подержанных автомобилей / компания по страхованию автомобилей могут установить инфраструктуру с камерами высокого разрешения под подходящими углами и в подходящем месте, чтобы щелкать стандартизированные (размерные) изображения различных частей кузова (спереди, сзади, сбоку и т. Д.) И могут обнаруживать все возможные внешние повреждения в автомобилях. . Эту концепцию можно использовать как мобильное приложение как решение API, что может упростить процесс оценки автомобиля.

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