Привет, ребята!!

Надеюсь, у вас все хорошо! Оглядываясь назад, последние несколько лет были действительно трудными из-за пандемии. Даже сегодня мир сталкивается с внезапным всплеском числа случаев Covid. Поэтому мы также должны максимально соблюдать меры предосторожности. Главное, что мы можем сделать, — это обеспечить, чтобы все носили маски для лица, так как это, по крайней мере, может снизить вероятность передачи болезни.

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

Мы собираемся реализовать этот проект, используя Keras и OpenCV. Я собираюсь разделить проект на два блога:

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

В этом блоге мы собираемся обсудить первую часть.

Без лишних слов давайте сразу перейдем к коду и рассмотрим шаги один за другим:

Шаг 1. Получение набора данных

Сначала нам нужен набор данных, верно? Вы можете скачать набор данных по этой ссылке:



Теперь просто скачайте файл и сохраните его. Вам не нужно распаковывать или извлекать его сейчас.

Перейдите на Google Диск и загрузите файл, который вы скачали сейчас.

Шаг 2. Подключение диска в Google Colab и распаковка набора данных

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

from google.colab import drive
drive.mount('/content/drive')

Используя приведенный выше код, мы импортируем диск, а затем монтируем его.

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

!unzip "/content/drive/MyDrive/FaceMask_Detection.zip" -d "/content/"

Внутри первого "" мы указываем путь к исходному файлу, который мы хотим разархивировать. Для пути к исходному файлу щелкните файл правой кнопкой мыши и выберите «Копировать путь». Теперь внутри второго "" поместите пункт назначения. Путь назначения: /content/.

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

В наборе обучающих данных 10000 изображений и 800 изображений в наборе проверочных данных.

Шаг 3. Импорт библиотек

Теперь импортируем нужные нам библиотеки

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D,  BatchNormalization
from tensorflow.keras.layers import Activation, Dropout, Flatten, Dense
from tensorflow.keras.optimizers import Adam

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

Шаг 4. Настройка каталогов

# Dimension of our images.
img_width, img_height = 150, 150

#Setting up the directories
train_data_dir = '/content/Face Mask Dataset/Train'
validation_data_dir = '/content/Face Mask Dataset/Validation'

Мы определяем размер изображения. Поэтому мы инициализируем значения img_width и image_height равными 150. Изображения в нашем наборе данных могут иметь любой размер, поэтому нам нужно преобразовать их все в один размер, прежде чем отправлять их в модель. После этого мы настраиваем каталоги обучения и проверки. Вам нужно щелкнуть правой кнопкой мыши по поезду и проверить папки на левой панели, а затем выбрать параметр «Копировать путь». Наконец, вставьте их внутрь «».

input_shape = (img_width, img_height, 3)
epochs = 50
batch_size = 32

Теперь мы определяем форму изображения как image_width * image_height * 3.Поскольку изображения имеют формат RGB, количество каналов будет равно 3. Мы также объявляем другие гиперпараметры, такие как число эпох и размер пакета.

Шаг 4. Предварительная обработка данных

Здесь то, что мы делаем, называется Увеличение данных.

Что такое увеличение данных?

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

Теперь существуют различные методы увеличения данных. Давайте посмотрим на код, который мы используем, и посмотрим, какие методы мы использовали.

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1./ 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

Теперь ImageDataGenerator — это класс, который помогает выполнять эту аугментацию данных.

Аргументы:

  1. изменение масштаба. По сути, изменение масштаба — это техника нормализации. Таким образом, нормализация выполняется следующим образом: (x-min)/(max-min). Здесь x — значение пикселя. Итак, каково возможное максимальное и минимальное значение пикселя? Да255 и 0. Итак, наша формула выглядит так (x*1./255). Итак, после деления значений пикселей на 255 мы приносят диапазон значений пикселей от 0–1. Это упрощает расчеты, так как теперь нам приходится иметь дело с меньшими числами. А также облегчает процесс оптимизации.
  2. shear_range : отображение сдвига — это линейная карта, которая смещает каждую точку в фиксированном направлении на определенную величину. Таким образом, здесь диапазон сдвига представляет интенсивность сдвига.
  3. zoom_range: указывает диапазон масштабирования, который будет применяться к изображению.
  4. horizontal_flip: изображение будет перевернуто по горизонтали.

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



Теперь мы должны применить это к набору обучающих данных.

Итак, мы используем следующий код:

#this generates batches of augment data for training
train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

Таким образом, flow_from_directory() будет использоваться для создания пакетов дополненных данных. Теперь что мы передаем в качестве аргументов -

  1. train_data_dir — это каталог, содержащий обучающие изображения.
  2. target_size равен размеру изображения
  3. batch_size, как мы уже определили
  4. class_mode: будет двоичным, поскольку здесь у нас есть только 2 класса, категориальный для более чем 2 классов

Теперь аналогичным образом мы применим дополнение к набору данных проверки:

# this is the augmentation configuration we will use for validating
val_datagen = ImageDataGenerator(rescale=1./255)

#this generates batches of augment data for validating
validation_generator = val_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

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

ПРИМЕЧАНИЕ. Масштабирование является обязательной операцией, которую необходимо выполнять во всех случаях.

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

Шаг 5. Создание модели

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

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

from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2

mobilenet = MobileNetV2(weights = "imagenet",include_top = False,input_shape=(150,150,3))

Аргументы:

  • веса : файлы с обучаемыми весами для загрузки. «imagenet» предназначен для весов, обученных набору данных ImageNet. Если вам не нужны веса, просто поставьте здесь «Нет».
  • include_top: следует ли включать Сведение слоя и полностью связанные слои или нет.
  • input_shape: обозначает форму передаваемых входных изображений.

Вы можете проверить архитектуру MobileNetV2, которую мы загрузили, используя:

mobilenet.summary()

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

for layer in mobilenet.layers:
    layer.trainable = False

Мы перебираем слои один за другим и делаем их необучаемыми с помощью .trainable= False.

Теперь часть классификатора построена.

model = Sequential()
model.add(mobilenet)
model.add(Flatten())
model.add(Dense(1,activation="sigmoid"))

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

Теперь мы продолжим добавлять слои, используя .add().

Сначала добавляется мобильная сеть.

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

Но почему мы используем flatten??

Трехмерные матрицы прямоугольной или кубической формы не могут быть введены в нейроны. Поэтому используется сглаживание. Он выравнивает данные в одномерный массив для ввода их на следующий слой, который будет плотным слоем. Мы сглаживаем выходные данные сверточных слоев, чтобы создать один длинный вектор признаков. И это связано с окончательной моделью классификации, которая называется полностью связанные слои. Таким образом, следует следующий порядок: Сначала слева направо, затем сверху вниз. Когда все значения из первого слоя упорядочиваются, он перемещается на следующий уровень, и так продолжается.

Теперь последний слой. Поскольку у нас всего 2 класса, мы используем там 1 нейрон и сигмовидную функцию активации. Если сигмоид выводит значение 0, то это говорит о классе 0, а значение 1 означает класс 1.

Мы можем реализовать это с помощью функции активации softmax. Но в этом случае мы должны использовать 2 нейрона.

Для многоклассовой классификации количество нейронов в последнем слое будет равно количеству классов и активации = «softmax».

Шаг 6. Компиляция модели

Теперь, когда проектирование модели завершено. Мы составим его:

model.compile(optimizer="adam",loss="binary_crossentropy",metrics ="accuracy")

Что же означает компиляция модели? Здесь в основном мы будем сообщать параметры модели, такие как:

  • Какие убытки использовать для расчета функции стоимости J? Как и здесь, поскольку у нас есть два класса, мы используем binary_crossentropy.
  • Какой оптимизатор следует использовать для обновления во время обратного распространения? Например, здесь мы используем 'adam'.
  • Какой показатель мы будем использовать для оценки его эффективности? Здесь мы определили точность.

Это гиперпараметры, которые мы принимаем сами

Теперь, когда мы сделали все это, давайте визуализируем модель, используя

model.summary()

Итак, вот что мы получаем:

Таким образом, это обеспечивает обобщение всей модели.

Обратите внимание, что все параметры в mobilenetv2 не поддаются обучению.

Теперь мы устанавливаем размеры пакетов:

#Setting up the batchsizes.
nb_train_samples = 10000
nb_validation_samples = 800

Вы можете проверить, каким классам присвоен какой номер, используя:

print(train_generator.class_indices)

WithMask присвоен класс 0, а WithoutMask — 1.

Шаг 7. Определение обратного вызова EarlyStopping

Теперь здесь мы собираемся использовать что-то под названием EarlyStopping.

Что такое ранняя остановка?

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

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

Какое может быть решение?

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

Для этого нам нужен обратный вызов.

Что такое обратный вызов?

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

from keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_accuracy', mode='max', verbose=1,patience=2,restore_best_weights=True)

Аргументы:

  • monitor : что нужно отслеживать
  • режим: min – обучение останавливается, когда отслеживаемое количество перестает уменьшаться, max – обучение прекращается, когда отслеживаемое количество прекращает увеличиваться, auto – режим определяется автоматически на основе имени контролируемого параметра.
  • verbose : режим многословия.
  • терпение : нет. эпох без улучшения, после чего обучение будет остановлено
  • restore_best_weights: следует ли восстанавливать лучшие веса, в противном случае сохраняются последние.

Хотите узнать больше о ранней остановке? Вы можете проверить мой блог:



Шаг 8. Обучение модели

Теперь, наконец, мы обучим нашу модель с помощью .fit_generator().

model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size,callbacks=[es])

Аргументы:

  • Дополненный набор данных о поездах, который мы создали
  • Количество шагов для обучающих данных: количество шагов рассчитывается как общее количество обучающих выборок/размер_пакета. Скажем, размер пакета равен 16. Затем, когда передается 16 изображений, вычисляется J, обновление происходит после обратного распространения, мы говорим, что один шаг завершен. Когда все изображения в наборе данных покрыты, мы говорим, что одна эпоха завершена.
  • Количество эпох
  • Данные проверки, куда мы передаем обработанный набор данных проверки.
  • И количество шагов для проверки набора данных, которое рассчитывается по той же формуле.
  • Определенные нами обратные вызовы. У нас может быть несколько обратных вызовов, поэтому мы передаем их в виде списка. В нашем случае у нас есть только один обратный вызов.

Теперь начинается обучение :

Здесь, поскольку точность проверки перестала увеличиваться, обучение останавливается только после 5 эпох.

Шаг 9. Сохранение архитектуры и весов модели

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

Итак, для этого мы используем этот код

model.save_weights('FaceMask_Detection_second_try_three.h5')
with open('model_architecture_FaceMask_Detection_second_try_three.json','w') as f:
    f.write(model.to_json())

Таким образом, первая строка кода сохраняет веса модели в файле .h5, а следующая строка кода сохраняет архитектуру модели в формате файла .json. Мы используем with open для открытия файла в режиме записи, а затем с помощью .to_json() сохраняем его в формате json.

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

Код можно найти по этой ссылке:



Не стесняйтесь комментировать ниже, если у вас есть какие-либо сомнения.

Следующая часть: реализация OpenCV: https://aoishidas28.medium.com/realtime-face-mask-detector-project-opencv-implementation-f3938ec74a5e

Всего наилучшего и удачного обучения..!!