Предложение проекта идентификации препятствий на открытом воздухе для слепых с DeepLabv3+
Много лет работаю волонтером с людьми с нарушениями зрения. В прошлую новогоднюю ночь я гулял со слепой дамой, достаточно знакомой со своим районом после десятилетий жизни, а ей все еще нужна пара глаз в случаях непредвиденных препятствий на тротуарах: брошенная елка после фестиваля, неправильно припаркованные автомобили , новые рабочие места и т. д. К сожалению, у нас меньше волонтеров, чем нужно, и некоторым слепым людям приходится по нескольку раз ждать прогулки с сопровождением.
Поэтому я подумал, как я могу предложить решение, которое поможет моим слабовидящим друзьям выявлять препятствия, когда они выходят наедине с машинным обучением.
В этой статье я предлагаю подход, который:
- использует смартфон для захвата изображений в реальном времени в качестве входных данных модели глубокого обучения для распознавания объектов;
- предоставляет голосовое руководство, позволяющее слабовидящим людям понять о возможных препятствиях на пути.
Теперь я предоставлю более подробную информацию о важной части этого проекта: системе распознавания объектов с глубоким обучением. Весь код, использованный в этой статье, можно найти в этой блокноте.
Набор данных
Система распознавания объектов может быть реализована с помощью семантической сегментации, то есть присвоения семантических меток (таких как дерево, тротуар) каждому пикселю входного изображения.
Подготовка соответствующего набора данных является важным шагом для выполнения задачи.
Поскольку я работаю волонтером в Париже, я буду обучать модель глубокого обучения на наборе данных изображение городских пейзажей. Исходный набор данных городских пейзажей доступен на сайте 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