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

Программа выполнена в рамках программы Data Scientist Nanodegree «Capstone Project».

Введение проблемы:

Правильно классифицировать породу собаки по ее фотографии и получить наиболее похожую на человека породу собаки, если дана фотография человека.

Стратегия решения проблемы:

мы решим эту проблему, используя сверточные нейронные сети (CNN)

Метрики:

мы будем использовать метрику точности.

EDA :

Прежде всего, нам нужно классифицировать фотографию, если это фотография собаки, которую она обнаружит, и если это фотография человека, она обнаружит ее, и узнать, если это ни то, ни другое.

Итак, мы начнем с создания детектора человеческого лица: я использовал cv2 haarcascade для обнаружения человеческих лиц:

import cv2                
import matplotlib.pyplot as plt                        
%matplotlib inline                               

# extract pre-trained face detector
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_alt.xml')

# load color (BGR) image
img = cv2.imread(human_files[3])
# convert BGR image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Затем, чтобы построить функцию детектора лица, чтобы она возвращала True, если это было человеческое лицо, и False в противном случае.

# returns "True" if face is detected in image stored at img_path
def face_detector(img_path):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray)
    return len(faces) > 0

Результаты были приемлемыми:

процент обнаруженных человеческих лиц из человеческих файлов: 100%

процент обнаруженных человеческих лиц из файлов с собаками: 11%

Затем, чтобы построить наш детектор собак: я использовал ResNent50, чтобы определить, была ли это фотография собаки или нет.

from keras.applications.resnet50 import ResNet50

# define ResNet50 model
ResNet50_model = ResNet50(weights='imagenet')

Но нам нужно предварительно обработать входные данные, поэтому размер изображения должен быть 224×224.

from keras.preprocessing import image                  
from tqdm import tqdm

def path_to_tensor(img_path):
    # loads RGB image as PIL.Image.Image type
    img = image.load_img(img_path, target_size=(224, 224))
    # convert PIL.Image.Image type to 3D tensor with shape (224, 224, 3)
    x = image.img_to_array(img)
    # convert 3D tensor to 4D tensor with shape (1, 224, 224, 3) and return 4D tensor
    return np.expand_dims(x, axis=0)

def paths_to_tensor(img_paths):
    list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
    return np.vstack(list_of_tensors)

Затем построить всю функцию так, чтобы она возвращала True, если это изображение собаки, и False в противном случае.

Результаты были идеальными:

процент изображений в human_files_short с обнаруженной собакой: 0,0 %

процент изображений в dog_files_short с обнаруженной собакой: 100,0 %

Моделирование и настройка гиперпараметров:

Теперь мы построили наши детекторы, так что пришло время построить наши классификаторы:

Я построил три разные модели:

- one from scratch 
- one using VGG16 
- The last one and the main one used , Was built using transfer learning with ResNet50 

Первый, который я построил с нуля:

Я использовал 32–64–128, чтобы захватить как можно больше шаблонов из исходной фотографии. И я использовал функцию активации «relu», потому что она давала лучшую точность, чем другие функции активации, такие как «tanh». Я использовал глобальное среднее объединение в конец, чтобы уменьшить количество параметров. Затем использовал плотный слой со 100 узлами для соединения шаблонов. В конце я добавил плотный слой с количеством существующих классов (133) с softmax.

И я использовал оптимизатор «адам».

from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.models import Sequential

model = Sequential()

### TODO: Define your architecture.
model.add(Conv2D(filters=32, kernel_size=2, padding='same', activation='relu', 
                        input_shape=(224, 224, 3)))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(filters=64, kernel_size=2, padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(filters=128, kernel_size=2, padding='same', activation='relu'))
model.add(GlobalAveragePooling2D())
model.add(Dropout(0.2))
#model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(133, activation='softmax'))


model.summary()

Что касается второго, я использовал VGG16, не добавляя к нему никаких слоев:

VGG16_model = Sequential()
VGG16_model.add(GlobalAveragePooling2D(input_shape=train_VGG16.shape[1:]))
VGG16_model.add(Dense(133, activation='softmax'))

VGG16_model.summary()

В третьей модели и той, что использовалась, я использовал трансферное обучение в ResNet50, добавив поверх него плотный слой.

### TODO: Define your architecture.
resnet50_model = Sequential()
resnet50_model.add(GlobalAveragePooling2D(input_shape=train_ResNet_50.shape[1:]))
resnet50_model.add(Dense(150,activation='relu'))
resnet50_model.add(Dropout(0.5))
resnet50_model.add(Dense(133, activation='softmax'))

resnet50_model.summary()

Результаты:

Модель, которую я построил с нуля. Точность теста составила 4,426%.

Модель VGG16 имела точность испытаний 41,5072%.

Модель ResNet50, с которой я использовал трансферное обучение, имела точность теста 82,1770%.

Вывод:

После этого все, что осталось, это построить алгоритм, чтобы объединить все это в простую функцию:

Если бы это была человеческая картинка, найди к ней наиболее похожую породу собак,

Если это была фотография собаки, классифицируйте ее.

Если это ни то, ни другое, завершите работу оператором «неверный ввод».

### TODO: Write your algorithm.
### Feel free to use as many code cells as needed.
def dog_human_preds(img_path):
    if(face_detector(img_path)):
        print('That is a human')
        img = cv2.imread(img_path)
        
        # convert BGR image to RGB for plotting
        cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        # display the image, along with bounding box
        plt.imshow(cv_rgb)
        plt.show()
        bottleneck_feature = extract_Resnet50(path_to_tensor(img_path))
        # obtain predicted vector
        predicted_vector = resnet50_model.predict(bottleneck_feature)
        # return dog breed that is predicted by the model
        return dog_names[np.argmax(predicted_vector)]
        
    if(dog_detector(img_path)):
        print('That is a dog')
        img = cv2.imread(img_path)
        
        # convert BGR image to RGB for plotting
        cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        # display the image, along with bounding box
        plt.imshow(cv_rgb)
        plt.show()
        bottleneck_feature = extract_Resnet50(path_to_tensor(img_path))
        # obtain predicted vector
        predicted_vector = resnet50_model.predict(bottleneck_feature)
        # return dog breed that is predicted by the model
        return dog_names[np.argmax(predicted_vector)]
    img = cv2.imread(img_path)
        # convert BGR image to grayscale
        
        # convert BGR image to RGB for plotting
    cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        # display the image, along with bounding box
    plt.imshow(cv_rgb)
    plt.show()
    
    return 'invalid input,This neither a human nor a dog'

Если мы увидим примеры того, как это работает:

Предсказание породы собаки:

Предсказание наиболее похожей на человека породы собак:

Предсказывая, что это ни собака, ни человек картина:

Возможные улучшения:

1- Использовать детектор лиц, использующий подход глубокого обучения.

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

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

ВОТ И ВСЕ!!!

Спасибо за чтение .

Буду очень благодарен за любой отзыв от вас!

Ссылка на репо на Github здесь.

Мой LinkedIn здесь.