<kaggle_start><data_title>Face Detection in Images<data_description>### Context

Faces in images marked with bounding boxes. Have around 500 images with around 1100 faces manually tagged via bounding box.

To visualize the dataset and see how the dataset looks (actual images with tags) please see: https://dataturks.com/projects/devika.mishra/face_detection


### Content

Some examples from the dataset:

![enter image description here][1]

![enter image description here][2]<data_name>face-detection-in-images
<code>import numpy as np
import pandas as pd
import cv2 as cv
import os
import matplotlib.pyplot as plt
from tqdm.notebook import tqdm
import glob

# https://realpython.com/traditional-face-detection-python/
face_cascade = cv.CascadeClassifier(
    "/kaggle/input/haarcascades/haarcascade_frontalface_alt.xml"
)


def detect_faces(img):
    grey_image = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    detected_faces = face_cascade.detectMultiScale(grey_image)
    return detected_faces


def crop_face(img):
    faces = detect_faces(img)
    if len(faces) == 0:
        return img
    else:
        column, row, width, height = faces[0]
        cropped = img[row : row + height, column : column + width]
        return cv.resize(cropped, img.shape[0:2][::-1])


image = cv.imread(
    "/kaggle/input/celeba-dataset/img_align_celeba/img_align_celeba/000001.jpg"
)
fig, ax = plt.subplots(1, 2)
ax[0].imshow(image)
ax[1].imshow(crop_face(image))


# # Importing Data
# Each identity has to have its own folder
import pandas as pd
from shutil import copyfile

train_size = 20
file = "/kaggle/input/identity-celeba/identity_CelebA.txt"
identities = pd.read_csv(file, delimiter=" ", names=["file", "identity"])
source_dir = "/kaggle/input/celeba-dataset/img_align_celeba/img_align_celeba/%s"
target_dir_train = "/kaggle/working/train/%d/"
target_dir_test = "/kaggle/working/test/%d/"
for _, file, identity in tqdm(list(identities.itertuples())):
    if identity <= train_size:
        dest_dir = target_dir_train if identity <= train_size else target_dir_test
        dest_dir = dest_dir % identity
        os.makedirs(dest_dir, exist_ok=True)
        copyfile(source_dir % file, dest_dir + file)


def show_class(class_name, cl="train"):
    # Check to make sure that all files in each directory are of the same person (sanity check)
    files = glob.glob("/kaggle/working/%s/%s/*" % (cl, class_name))
    fig, ax = plt.subplots(1, len(files), figsize=(20, 10))
    for index, file in enumerate(files):
        ax[index].imshow(cv.imread(file))
        ax[index].axis("off")
    plt.show()


show_class(7)
# Create the image preprocessor
from keras.preprocessing.image import ImageDataGenerator
import random


def preprocess_image(img):
    # image must be an int for cropping and float for Keras
    return


train_directory = "/kaggle/working/train/"
test_directory = "/kaggle/working/train/"
batch_size = 16


class DirectoryFlow:
    def __init__(self, directory, batch_size):
        self.directory = directory
        self.batch_size = batch_size
        self.file_structure = {
            int(f): [
                directory + "%s/%s" % (f, file_name)
                for file_name in os.listdir(directory + f)
            ]
            for f in os.listdir(directory)
        }
        self.classes = list(self.file_structure.keys())
        print("Loaded %d classes" % len(self.classes))

    def read_image(self, file):
        img = cv.imread(file)
        img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
        return crop_face(img.astype("uint8")).astype("float32") / 255

    def next(self, class_name=None):
        if class_name is None:
            class_name = random.choice(self.classes)
        item = random.choice(self.file_structure[class_name])
        return self.read_image(item), class_name

    def next_batch(self):
        images = []
        labels = np.zeros((self.batch_size))
        for i in range(self.batch_size):
            image, class_name = self.next()
            images.append(image)
            labels[i] = class_name
        return np.array(images), labels


datagen_train = DirectoryFlow(train_directory, batch_size)
# datagen_test = DirectoryFlow(test_directory)


# # Modeling
# https://github.com/aleju/face-comparer/blob/master/train.py#L252
from keras.layers import (
    Input,
    Dense,
    Activation,
    Dropout,
    Flatten,
    Dense,
    Add,
    Conv2D,
    MaxPooling2D,
    Lambda,
)
from keras.models import Model

input_shape = (218, 178, 3)
input_face_left = Input(shape=input_shape, name="model_face_left")
input_face_right = Input(shape=input_shape, name="model_face_right")
input_face = Input(shape=input_shape)
face = Conv2D(32, kernel_size=(3, 3), activation="relu", padding="same", name="conv1")(
    input_face
)
face = MaxPooling2D((2, 2), name="mp1")(face)
face = Conv2D(32, kernel_size=(3, 3), activation="relu", padding="same", name="conv2")(
    face
)
face = MaxPooling2D((3, 3), name="mp2")(face)
output_face = Flatten(name="f1")(face)
model_face = Model(input_face, output_face)
model_face_left = model_face(input_face_left)
model_face_right = model_face(input_face_right)
merged_model = Lambda(
    lambda tensors: abs(tensors[0] - tensors[1]), name="absolute_difference"
)([model_face_left, model_face_right])
merged_model = Dense(64, activation="relu", name="d1")(merged_model)
merged_model = Dropout(0.1, name="drop1")(merged_model)
merged_model = Dense(64, activation="relu", name="d2")(merged_model)
merged_model = Dense(1, activation="sigmoid", name="out")(merged_model)
model = Model(
    inputs=[input_face_left, input_face_right], outputs=merged_model, name="lr_merger"
)
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
model.summary()
from IPython.display import Image
from keras.utils import plot_model

plot_model(model, to_file="/kaggle/working/model.png", show_shapes=True)
Image("/kaggle/working/model.png")


class CustomBatchIterator:
    def __init__(self, datagen, batch_size):
        self.datagen = datagen
        self.batch_size = batch_size

    def make_batch(self):
        images, labels = self.datagen.next_batch()
        output_pairs = [np.zeros((self.batch_size, *images[0].shape)) for i in range(2)]
        output_labels = np.zeros(self.batch_size)
        output_labels[: self.batch_size // 2] = 1
        for i in range(self.batch_size // 2):
            label = labels[i]
            random_image, _ = self.datagen.next(label)
            output_pairs[0][i] = images[i]
            output_pairs[1][i] = random_image
        for i in range(self.batch_size // 2, self.batch_size):
            label = labels[i]
            while True:
                random_label = random.choice(self.datagen.classes)
                if random_label != label:
                    break
            random_image, _ = self.datagen.next(random_label)
            output_pairs[0][i] = images[i]
            output_pairs[1][i] = random_image
        return output_pairs, output_labels

    def __iter__(self):
        return self

    def __next__(self):
        return self.make_batch()


def show_batch_pairs(image_batch_pairs, label_batch):
    fig, ax = plt.subplots(len(image_batch_pairs[0]), 2, figsize=(20, 20))
    for r in range(len(image_batch_pairs[0])):
        for c in [0, 1]:
            ax[r, c].imshow(image_batch_pairs[c][r])
            ax[r, c].axis("off")
            ax[r, c].set_title("y=%d" % label_batch[r])


train_it = CustomBatchIterator(datagen_train, batch_size)
show_batch_pairs(*next(train_it))
model.fit_generator(train_it, steps_per_epoch=10, epochs=200)
<|endoftext|>
[{"Id": 32970077, "ScriptId": 9086782, "ParentScriptVersionId": NaN, "ScriptLanguageId": 9, "AuthorUserId": 4456277, "CreationDate": "04/30/2020 01:26:28", "VersionNumber": 8.0, "Title": "CSCI 4622: Final Project", "EvaluationDate": "04/30/2020", "IsChange": true, "TotalLines": 200.0, "LinesInsertedFromPrevious": 118.0, "LinesChangedFromPrevious": 0.0, "LinesUnchangedFromPrevious": 82.0, "LinesInsertedFromFork": NaN, "LinesDeletedFromFork": NaN, "LinesChangedFromFork": NaN, "LinesUnchangedFromFork": NaN, "TotalVotes": 0}]
[{"Id": 35851505, "KernelVersionId": 32970077, "SourceDatasetVersionId": 54972}, {"Id": 35851504, "KernelVersionId": 32970077, "SourceDatasetVersionId": 37705}, {"Id": 35851503, "KernelVersionId": 32970077, "SourceDatasetVersionId": 18147}, {"Id": 35851506, "KernelVersionId": 32970077, "SourceDatasetVersionId": 1104205}]
[{"Id": 54972, "DatasetId": 36341, "DatasourceVersionId": 57374, "CreatorUserId": 1853660, "LicenseName": "Unknown", "CreationDate": "07/12/2018 09:34:14", "VersionNumber": 1.0, "Title": "Face Detection in Images", "Slug": "face-detection-in-images", "Subtitle": "Image bounding box dataset to detect faces in images", "Description": "### Context\n\nFaces in images marked with bounding boxes. Have around 500 images with around 1100 faces manually tagged via bounding box.\n\nTo visualize the dataset and see how the dataset looks (actual images with tags) please see: https://dataturks.com/projects/devika.mishra/face_detection\n\n\n### Content\n\nSome examples from the dataset:\n\n![enter image description here][1]\n\n![enter image description here][2]\n\n### Acknowledgements\n\nOriginal location: https://dataturks.com/projects/devika.mishra/face_detection\n\n\n  [1]: https://storage.googleapis.com/bonsai-b808c.appspot.com/dataturks/extras/face_detection_dataset1.png\n  [2]: https://storage.googleapis.com/bonsai-b808c.appspot.com/dataturks/extras/face_detection_datatset_image2.png", "VersionNotes": "Initial release", "TotalCompressedBytes": 273830.0, "TotalUncompressedBytes": 273830.0}]
[{"Id": 36341, "CreatorUserId": 1853660, "OwnerUserId": 1853660.0, "OwnerOrganizationId": NaN, "CurrentDatasetVersionId": 54972.0, "CurrentDatasourceVersionId": 57374.0, "ForumId": 44755, "Type": 2, "CreationDate": "07/12/2018 09:34:14", "LastActivityDate": "07/12/2018", "TotalViews": 598479, "TotalDownloads": 23774, "TotalVotes": 536, "TotalKernels": 13}]
import numpy as np
import pandas as pd
import cv2 as cv
import os
import matplotlib.pyplot as plt
from tqdm.notebook import tqdm
import glob

# https://realpython.com/traditional-face-detection-python/
face_cascade = cv.CascadeClassifier(
    "/kaggle/input/haarcascades/haarcascade_frontalface_alt.xml"
)


def detect_faces(img):
    grey_image = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    detected_faces = face_cascade.detectMultiScale(grey_image)
    return detected_faces


def crop_face(img):
    faces = detect_faces(img)
    if len(faces) == 0:
        return img
    else:
        column, row, width, height = faces[0]
        cropped = img[row : row + height, column : column + width]
        return cv.resize(cropped, img.shape[0:2][::-1])


image = cv.imread(
    "/kaggle/input/celeba-dataset/img_align_celeba/img_align_celeba/000001.jpg"
)
fig, ax = plt.subplots(1, 2)
ax[0].imshow(image)
ax[1].imshow(crop_face(image))


# # Importing Data
# Each identity has to have its own folder
import pandas as pd
from shutil import copyfile

train_size = 20
file = "/kaggle/input/identity-celeba/identity_CelebA.txt"
identities = pd.read_csv(file, delimiter=" ", names=["file", "identity"])
source_dir = "/kaggle/input/celeba-dataset/img_align_celeba/img_align_celeba/%s"
target_dir_train = "/kaggle/working/train/%d/"
target_dir_test = "/kaggle/working/test/%d/"
for _, file, identity in tqdm(list(identities.itertuples())):
    if identity <= train_size:
        dest_dir = target_dir_train if identity <= train_size else target_dir_test
        dest_dir = dest_dir % identity
        os.makedirs(dest_dir, exist_ok=True)
        copyfile(source_dir % file, dest_dir + file)


def show_class(class_name, cl="train"):
    # Check to make sure that all files in each directory are of the same person (sanity check)
    files = glob.glob("/kaggle/working/%s/%s/*" % (cl, class_name))
    fig, ax = plt.subplots(1, len(files), figsize=(20, 10))
    for index, file in enumerate(files):
        ax[index].imshow(cv.imread(file))
        ax[index].axis("off")
    plt.show()


show_class(7)
# Create the image preprocessor
from keras.preprocessing.image import ImageDataGenerator
import random


def preprocess_image(img):
    # image must be an int for cropping and float for Keras
    return


train_directory = "/kaggle/working/train/"
test_directory = "/kaggle/working/train/"
batch_size = 16


class DirectoryFlow:
    def __init__(self, directory, batch_size):
        self.directory = directory
        self.batch_size = batch_size
        self.file_structure = {
            int(f): [
                directory + "%s/%s" % (f, file_name)
                for file_name in os.listdir(directory + f)
            ]
            for f in os.listdir(directory)
        }
        self.classes = list(self.file_structure.keys())
        print("Loaded %d classes" % len(self.classes))

    def read_image(self, file):
        img = cv.imread(file)
        img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
        return crop_face(img.astype("uint8")).astype("float32") / 255

    def next(self, class_name=None):
        if class_name is None:
            class_name = random.choice(self.classes)
        item = random.choice(self.file_structure[class_name])
        return self.read_image(item), class_name

    def next_batch(self):
        images = []
        labels = np.zeros((self.batch_size))
        for i in range(self.batch_size):
            image, class_name = self.next()
            images.append(image)
            labels[i] = class_name
        return np.array(images), labels


datagen_train = DirectoryFlow(train_directory, batch_size)
# datagen_test = DirectoryFlow(test_directory)


# # Modeling
# https://github.com/aleju/face-comparer/blob/master/train.py#L252
from keras.layers import (
    Input,
    Dense,
    Activation,
    Dropout,
    Flatten,
    Dense,
    Add,
    Conv2D,
    MaxPooling2D,
    Lambda,
)
from keras.models import Model

input_shape = (218, 178, 3)
input_face_left = Input(shape=input_shape, name="model_face_left")
input_face_right = Input(shape=input_shape, name="model_face_right")
input_face = Input(shape=input_shape)
face = Conv2D(32, kernel_size=(3, 3), activation="relu", padding="same", name="conv1")(
    input_face
)
face = MaxPooling2D((2, 2), name="mp1")(face)
face = Conv2D(32, kernel_size=(3, 3), activation="relu", padding="same", name="conv2")(
    face
)
face = MaxPooling2D((3, 3), name="mp2")(face)
output_face = Flatten(name="f1")(face)
model_face = Model(input_face, output_face)
model_face_left = model_face(input_face_left)
model_face_right = model_face(input_face_right)
merged_model = Lambda(
    lambda tensors: abs(tensors[0] - tensors[1]), name="absolute_difference"
)([model_face_left, model_face_right])
merged_model = Dense(64, activation="relu", name="d1")(merged_model)
merged_model = Dropout(0.1, name="drop1")(merged_model)
merged_model = Dense(64, activation="relu", name="d2")(merged_model)
merged_model = Dense(1, activation="sigmoid", name="out")(merged_model)
model = Model(
    inputs=[input_face_left, input_face_right], outputs=merged_model, name="lr_merger"
)
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
model.summary()
from IPython.display import Image
from keras.utils import plot_model

plot_model(model, to_file="/kaggle/working/model.png", show_shapes=True)
Image("/kaggle/working/model.png")


class CustomBatchIterator:
    def __init__(self, datagen, batch_size):
        self.datagen = datagen
        self.batch_size = batch_size

    def make_batch(self):
        images, labels = self.datagen.next_batch()
        output_pairs = [np.zeros((self.batch_size, *images[0].shape)) for i in range(2)]
        output_labels = np.zeros(self.batch_size)
        output_labels[: self.batch_size // 2] = 1
        for i in range(self.batch_size // 2):
            label = labels[i]
            random_image, _ = self.datagen.next(label)
            output_pairs[0][i] = images[i]
            output_pairs[1][i] = random_image
        for i in range(self.batch_size // 2, self.batch_size):
            label = labels[i]
            while True:
                random_label = random.choice(self.datagen.classes)
                if random_label != label:
                    break
            random_image, _ = self.datagen.next(random_label)
            output_pairs[0][i] = images[i]
            output_pairs[1][i] = random_image
        return output_pairs, output_labels

    def __iter__(self):
        return self

    def __next__(self):
        return self.make_batch()


def show_batch_pairs(image_batch_pairs, label_batch):
    fig, ax = plt.subplots(len(image_batch_pairs[0]), 2, figsize=(20, 20))
    for r in range(len(image_batch_pairs[0])):
        for c in [0, 1]:
            ax[r, c].imshow(image_batch_pairs[c][r])
            ax[r, c].axis("off")
            ax[r, c].set_title("y=%d" % label_batch[r])


train_it = CustomBatchIterator(datagen_train, batch_size)
show_batch_pairs(*next(train_it))
model.fit_generator(train_it, steps_per_epoch=10, epochs=200)
