Предложение проекта идентификации препятствий на открытом воздухе для слепых с DeepLabv3+

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

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

В этой статье я предлагаю подход, который:

  1. использует смартфон для захвата изображений в реальном времени в качестве входных данных модели глубокого обучения для распознавания объектов;
  2. предоставляет голосовое руководство, позволяющее слабовидящим людям понять о возможных препятствиях на пути.

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

Набор данных

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

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

Поскольку я работаю волонтером в Париже, я буду обучать модель глубокого обучения на наборе данных изображение городских пейзажей. Исходный набор данных городских пейзажей доступен на сайте cityscapes-dataset.com, который предоставляется бесплатно академическим и неакадемическим организациям для некоммерческих целей, таких как академические исследования, обучение, научные публикации или личные эксперименты.

Он содержит помеченные изображения городских уличных сцен с 2975 файлами обучающих изображений и 500 файлами проверочных изображений. Каждый файл изображения имеет размер 256x512 пикселей, и каждый файл представляет собой композицию, в которой исходная фотография находится в левой половине изображения, а изображение с меткой (результат семантической сегментации) — в правой половине.

Вот пример изображений.

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

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

Приведенные ниже функции создают набор данных для обучения и проверки для модели:

1. разделение входного и выходного изображений;

2. нормализация входного изображения;

3. присвоение каждому пикселю выходного изображения целого числа в качестве метки.

train_images=[]
train_masks=[]
val_images=[]
val_masks=[]

def getlabel(img):
    """
    turn a 3 channel RGB image to 1 channel index image
    """
    height, width, ch = img.shape
    m_lable = np.zeros((height, width, 1), dtype=np.uint8)
    for w in range(width):
        for h in range(height):
            b,g,r=img[h, w, :]
m_lable[h,w,:]=np.argmin(np.linalg.norm(np.array([r,g,b])-color_palette,axis=1),axis=0)
    return m_lable

def load_images(path):
    temp_img,temp_masks=[],[]
    images=glob(os.path.join(path,'*.jpg'))
    for i in tqdm(images):
        i = cv2.imread(i)
        img = i[:, :256]
        img = cv2.normalize(img, None, 0, 1, cv2.NORM_MINMAX, cv2.CV_32F)
        msk = i[:, 256:]
        label = getlabel(msk)
        temp_masks.append(label)
        temp_img.append(img)
    return np.array(temp_img),np.array(temp_masks)
train_images,train_masks=load_images(train_path)
val_images,val_masks=load_images(val_path)

Обучение модели

В этом разделе мы построим модель семантической сегментации с помощью DeepLabV3+ на наборе данных городских пейзажей.

DeepLab — это архитектура для семантической сегментации, основанная на DeepLab со схемой объединения пространственных пирамид Atrous (ASPP). Причина использования ASPP вместо классических методов пулинга заключается в том, что было показано, что чем выше частота дискретизации, тем меньше число действительных весов фильтров.

В этой статье приводятся результаты с DeepLabV3+, последней версией DeepLab, расширяющей своего предка DeepLabV3 за счет добавления структуры кодер-декодер. Приведенный ниже код строит DeepLabV3+ путем построения расширенного блока свертки, который содержит один слой свертки, за которым следует слой пакетной нормализации, и ASPP, который содержит один средний пул, один блок свертки 1*1, один слой повышения дискретизации, за которым следует последовательность блоков свертки с возрастающей скоростью расширения. .

def convolution_block(
    block_input,
    num_filters=256,
    kernel_size=3,
    dilation_rate=1,
    padding="same",
    use_bias=False,
):
    x = layers.Conv2D(
        num_filters,
        kernel_size=kernel_size,
        dilation_rate=dilation_rate,
        padding="same",
        use_bias=use_bias,
        kernel_initializer=keras.initializers.HeNormal(),
    )(block_input)
    x = layers.BatchNormalization()(x)
    return tf.nn.relu(x)


def DilatedSpatialPyramidPooling(dspp_input):
    dims = dspp_input.shape
    x = layers.AveragePooling2D(pool_size=(dims[-3], dims[-2]))(dspp_input)
    x = convolution_block(x, kernel_size=1, use_bias=True)
    out_pool = layers.UpSampling2D(
        size=(dims[-3] // x.shape[1], dims[-2] // x.shape[2]), interpolation="bilinear",
    )(x)

    out_1 = convolution_block(dspp_input, kernel_size=1, dilation_rate=1)
    out_6 = convolution_block(dspp_input, kernel_size=3, dilation_rate=6)
    out_12 = convolution_block(dspp_input, kernel_size=3, dilation_rate=12)
    out_18 = convolution_block(dspp_input, kernel_size=3, dilation_rate=18)

    x = layers.Concatenate(axis=-1)([out_pool, out_1, out_6, out_12, out_18])
    output = convolution_block(x, kernel_size=1)
    return output

def DeeplabV3Plus(image_size, num_classes):
    model_input = keras.Input(shape=(image_size, image_size, 3))
    resnet50 = keras.applications.ResNet50(
        weights="imagenet", include_top=False, input_tensor=model_input
    )
    x = resnet50.get_layer("conv4_block6_2_relu").output
    x = DilatedSpatialPyramidPooling(x)

    input_a = layers.UpSampling2D(
        size=(image_size // 4 // x.shape[1], image_size // 4 // x.shape[2]),
        interpolation="bilinear",
    )(x)
    input_b = resnet50.get_layer("conv2_block3_2_relu").output
    input_b = convolution_block(input_b, num_filters=48, kernel_size=1)

    x = layers.Concatenate(axis=-1)([input_a, input_b])
    x = convolution_block(x)
    x = convolution_block(x)
    x = layers.UpSampling2D(
        size=(image_size // x.shape[1], image_size // x.shape[2]),
        interpolation="bilinear",
    )(x)
    model_output = layers.Conv2D(num_classes, kernel_size=(1, 1), padding="same")(x)
    return keras.Model(inputs=model_input, outputs=model_output)


model = DeeplabV3Plus(image_size=IMAGE_SIZE, num_classes=NUM_CLASSES)
model.summary()

loss = keras.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=0.001),
    loss=loss,
    metrics=["accuracy"],
)

history = model.fit(train_dataset,validation_data=val_dataset, epochs=15)

Вот графики точности поезда и точности проверки с 15 периодами обучения. Точность проверки достигает 84% после 15 периодов обучения.

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

Следующие шаги

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

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

Кроме того, незрячим людям также было бы полезно иметь представление о том, как далеко они находятся от препятствий. Конечно, мы можем обучить другую глубокую нейронную работу с помеченными данными. Не имея такого набора данных, я даю ей простое алгебраическое вычисление в качестве первой оценки расстояния между пользователем и объектом с помощью модели камеры-обскуры: то есть отношение размера объекта на изображении и размер объекта в реальной жизни такой же, как соотношение между фокусным расстоянием и расстоянием до объекта. Таким образом, мы можем получить оценку расстояния по фокусному_расстоянию*реальной_высоте/высоте_изображения.

Заключение

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

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

Рекомендации

[1] Мультиклассовая семантическая сегментация с использованием DeepLabV3+: https://keras.io/examples/vision/deeplabv3_plus/

[2] Кодер-декодер с Atrous Separable Convolution для семантической сегментации изображения: https://arxiv.org/pdf/1802.02611.pdf

[3] Обзор: DeepLabv3 — Atrous Convolution (семантическая сегментация): https://towardsdatascience.com/review-deeplabv3-atrous-convolution-semantic-segmentation-6d818bfd1d74