Переносное обучение (TL) – это исследовательская проблема в области машинного обучения (ML), которая фокусируется на сохранении знаний, полученных при решении одной задачи, и применении их к другой, но связанной проблеме.

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

VGG16 — модель сверточной нейронной сети, предложенная К. Симоняном и А. Зиссерманом из Оксфордского университета в статье Очень глубокие сверточные сети для крупномасштабного распознавания изображений. Точность модели достигает 92,7 % в тестах Top-5 в ImageNet, который представляет собой набор данных из более чем 14 миллионов изображений, принадлежащих к 1000 классам. Это была одна из известных моделей, представленных на ILSVRC-2014. Это улучшение по сравнению с AlexNet за счет замены больших фильтров размером с ядро ​​(11 и 5 в первом и втором сверточных слоях соответственно) несколькими фильтрами размера ядра 3 × 3 один за другим.

Проект:

  1. Соберите набор данных образцов лиц разных лиц в папках поезда и теста с разными папками для каждого лица.
  2. Используйте любую модель для обучения набора данных с помощью Transfer Learning.
  3. Распознавайте лица, используя свою модель

Предварительное условие до практического применения:

Список библиотек Python, которые необходимо установить:

  • тензорный поток
  • Керас
  • opencv
  • подушка
  • пустышка
conda install tensorflow keras opencv-python pillow numpy

Выполнение:

Перейдите в свой блокнот Jupyter и напишите код:

ШАГ 1.Сбор набора данных для лиц

# Assuming for collecting the dataset of images directories are already created under test and train directory as n0,n1,n1....
# acoording to the data of number of persons
# Load functions
def face_extractor(img):
    # Function detects faces and returns the cropped face
    # If no face detected, it returns the input image
    
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    faces = face_classifier.detectMultiScale(gray, 3, 5)
    
    if faces is ():
        return None
    
    # Crop all faces found
    for (x,y,w,h) in faces:
        cropped_face = img[y:y+h, x:x+w]
return cropped_face
def capture_images(t,name):
    # Initialize Webcam
    cap = cv2.VideoCapture(0)
    count = 1
# Collect 100 samples of your face from webcam input
    while True:
ret, frame = cap.read()
        if face_extractor(frame) is not None:
            count += 1
            face = cv2.resize(face_extractor(frame), (200, 200))
            #face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
# Save file in specified directory with unique name
            file_name_path = t+"image" + str(count) + '.jpg'
            cv2.imwrite(file_name_path, face)
# Put count on images and display live count
            cv2.putText(face, str(count), (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0,255,0), 2)
            cv2.imshow(name, face)
else:
            print("Face not found")
            pass
if cv2.waitKey(1) == 13 or count == 100: #13 is the Enter Key
            break
cap.release()
    cv2.destroyAllWindows()      
    return "Collecting Samples Complete"

Укажите количество людей, для которых вы хотите собрать набор данных об их лицах для обучения и тестирования.

import cv2
import numpy as np
import time
# Load HAAR face classifier
face_classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
file_path='C://Users//500060783//Desktop//MLOPS-WS//Projects//Face Recognizer Transfer Learning//Family//'
train_path=file_path+"train//"
test_path=file_path+"test//"
c=int(input("Enter the number of persons you want to capture image dataset"))
for i in range(c):
    print(f"Provide your images for testing dataset for person {i+1}")
    time.sleep(2)
    t=train_path+"n"+str(i)+"//"
    name="train images"
    out=capture_images(t,name)+f" for train set of person{i+1}"
    time.sleep(1)
    print(out)
    time.sleep(2)
    t=test_path+"n"+str(i)+"//"
    name="test images"
    out=capture_images(t,name)+f" for test set of person{i+1}"
    time.sleep(1)
    print(out)
    time.sleep(2)
print("Data Set completed successfully")

ШАГ 2.Загрузка модели VGG-16 и заморозка всех слоев

from keras.applications import vgg16
# VGG-16 was designed to work on 224 x 224 pixel input images sizes
img_rows, img_cols = 224, 224
# Re-loads the VGG-16 model without the top or FC layers
Vgg16 = vgg16.VGG16(weights = 'imagenet', 
                 include_top = False, 
                 input_shape = (img_rows, img_cols, 3))
# Here we freeze the last 4 layers 
# Layers are set to trainable as True by default
for layer in Vgg16.layers:
    layer.trainable = False
    
# Let's print our layers 
for (i,layer) in enumerate(Vgg16.layers):
    print(str(i) + " "+ layer.__class__.__name__, layer.trainable)

ШАГ 3.Добавьте полностью подключенную головку обратно на VGG-16.

def add_fc(bottom_model, num_classes):
    """creates the top or head of the model that will be 
    placed ontop of the bottom layers"""
    
    top_model = bottom_model.output
    top_model = GlobalAveragePooling2D()(top_model)
    top_model = Dense(1024,activation='relu')(top_model)
    top_model = Dense(1024,activation='relu')(top_model)
    top_model = Dense(512,activation='relu')(top_model)
    top_model = Dense(num_classes,activation='softmax')(top_model)
    return top_model

Добавление полностью подключенной головы обратно в модель

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten, GlobalAveragePooling2D
from keras.layers import Conv2D, MaxPooling2D, ZeroPadding2D
from keras.layers.normalization import BatchNormalization
from keras.models import Model
# Set our class number to 3 (Young, Middle, Old)
num_classes = 3
FC_Head = add_fc(Vgg16, num_classes)
model = Model(inputs = Vgg16.input, outputs = FC_Head)
print(model.summary())

ШАГ 4. Загрузка нашего набора данных о лицах

from keras.preprocessing.image import ImageDataGenerator
train_data_dir = 'Family/train'
validation_data_dir = 'Family/test'
# Let's use some data augmentaiton 
train_datagen = ImageDataGenerator(
      rescale=1./255,
      rotation_range=45,
      width_shift_range=0.3,
      height_shift_range=0.3,
      horizontal_flip=True,
      fill_mode='nearest')
 
validation_datagen = ImageDataGenerator(rescale=1./255)
 
# set our batch size (typically on most mid tier systems we'll use 16-32)
batch_size = 32
 
train_generator = train_datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_rows, img_cols),
        batch_size=batch_size,
        class_mode='categorical')
 
validation_generator = validation_datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_rows, img_cols),
        batch_size=batch_size,
        class_mode='categorical')

ШАГ 5. Модель обучения

from keras.optimizers import RMSprop
from keras.callbacks import ModelCheckpoint, EarlyStopping
checkpoint = ModelCheckpoint("face_recognize_vgg16.h5",
                             monitor="val_loss",
                             mode="min",
                             save_best_only = True,
                             verbose=1)
earlystop = EarlyStopping(monitor = 'val_loss', 
                          min_delta = 0, 
                          patience = 3,
                          verbose = 1,
                          restore_best_weights = True)
# we put our call backs into a callback list
callbacks = [earlystop, checkpoint]
# We use a very small learning rate 
model.compile(loss = 'categorical_crossentropy',
              optimizer = RMSprop(lr = 0.001),
              metrics = ['accuracy'])
# Enter the number of training and validation samples here
nb_train_samples = 605
nb_validation_samples = 255
# We only train 5 EPOCHS 
epochs = 5
batch_size = 16
history = model.fit_generator(
    train_generator,
    steps_per_epoch = nb_train_samples // batch_size,
    epochs = epochs,
    callbacks = callbacks,
    validation_data = validation_generator,
    validation_steps = nb_validation_samples // batch_size)

ШАГ 6. Загрузка нашего классификатора

from keras.models import load_model
classifier = load_model('face_recognize_vgg16.h5')

ШАГ 7. Проверка нашего классификатора на нескольких тестовых изображениях.

import os
import cv2
import numpy as np
from os import listdir
from os.path import isfile, join
face_recognize_dict = {"[0]": "Saurabh ", 
                      "[1]": "Piyush",
                      "[2]": "Aditya"}
face_recognize_dict_n = {"n0": "Saurabh ", 
                      "n1": "Piyush",
                      "n2": "Aditya"}
def draw_test(name, pred, im):
    face = face_recognize_dict[str(pred)]
    BLACK = [0,0,0]
    expanded_image = cv2.copyMakeBorder(im, 80, 0, 0, 100 ,cv2.BORDER_CONSTANT,value=BLACK)
    cv2.putText(expanded_image, face, (20, 60) , cv2.FONT_HERSHEY_SIMPLEX,1, (0,0,255), 2)
    cv2.imshow(name, expanded_image)
def getRandomImage(path):
    """function loads a random images from a random folder in our test path """
    folders = list(filter(lambda x: os.path.isdir(os.path.join(path, x)), os.listdir(path)))
    random_directory = np.random.randint(0,len(folders))
    path_class = folders[random_directory]
    print("Class - " + face_recognize_dict_n[str(path_class)])
    file_path = path + path_class
    file_names = [f for f in listdir(file_path) if isfile(join(file_path, f))]
    random_file_index = np.random.randint(0,len(file_names))
    image_name = file_names[random_file_index]
    return cv2.imread(file_path+"/"+image_name)
for i in range(0,10):
    input_im = getRandomImage("Family/test/")
    input_original = input_im.copy()
    input_original = cv2.resize(input_original, None, fx=0.5, fy=0.5, interpolation = cv2.INTER_LINEAR)
    
    input_im = cv2.resize(input_im, (224, 224), interpolation = cv2.INTER_LINEAR)
    input_im = input_im / 255.
    input_im = input_im.reshape(1,224,224,3) 
    
    # Get Prediction
    res = np.argmax(classifier.predict(input_im, 1, verbose = 0), axis=1)
    
    # Show image with predicted class
    draw_test("Prediction", res, input_original) 
    cv2.waitKey(0)
cv2.destroyAllWindows()

Наша модель правильно предсказала 9/10 изображений, что делает нашу модель приблизительной с точностью 90%.

БОНУС: прогнозирование в прямом эфире

import cv2
cap=cv2.VideoCapture(0)
while True:
    status,photo=cap.read()
    input_im=photo
    input_original = input_im.copy()
    input_original = cv2.resize(input_original, None, fx=0.5, fy=0.5, interpolation = cv2.INTER_LINEAR)
    
    input_im = cv2.resize(input_im, (224, 224), interpolation = cv2.INTER_LINEAR)
    input_im = input_im / 255.
    input_im = input_im.reshape(1,224,224,3) 
    
    # Get Prediction
    res = np.argmax(classifier.predict(input_im, 1, verbose = 0), axis=1)
    
    # Show image with predicted class
    draw_test("Prediction", res, input_original)
    
    if cv2.waitKey(1)==13:
        break
cv2.destroyAllWindows()
cap.release()

После исследования и обучения моделей из RESNET, Inception, MobileNet и VGG, VGG дает наилучшую точность и прогнозы в моем наборе данных.

Вы можете просмотреть код в моей учетной записи Github: https://github.com/saurabhagarwal43800/Face-Recognition-using-VGG-16.git