模式識別與機器學習作業——人臉識別與檢測

在這裏插入圖片描述

PR&ML Project Description -Project 1

1-The report

在這裏插入圖片描述

The answer can be seen in the code.

在這裏插入圖片描述
在這裏插入圖片描述

(3) Let N = 5 and 7, respectively. Repeat (2) for each N.

N = 5:

在這裏插入圖片描述

N=7:

在這裏插入圖片描述

(4) Repeat (2) and (3) for Fisherfaces. Compare the simulation results of Eigenfaces and Fisher-faces, and describe your findings.

N = 3:

在這裏插入圖片描述

N = 5:

在這裏插入圖片描述

N = 7:

在這裏插入圖片描述

在這裏插入圖片描述

There I cover face detection using :

  1. Haar Cascade Classifiers using OpenCV
  2. Histogram of Oriented Gradients using Dlib

1. Cascade Classifiers

Cascade classifier, or namely cascade of boosted classifiers working with haar-like features, is a special case of ensemble learning, called boosting. It typically relies on Adaboost classifiers (and other models such as Real Adaboost, Gentle Adaboost or Logitboost). Cascade classifiers are trained on a few hundred sample images of image that contain the object we want to detect, and other images that do not contain those images.

How can we detect if a face is there or not ? There is an algorithm, called Viola–Jones object detection framework, that includes all the steps required for live face detection :

  1. Haar Feature Selection, features derived from Haar wavelets
  2. Create integral image
  3. Adaboost Training
  4. Cascading Classifiers

The original paper was published in 2001.

1.1 Haar Feature Selection

There are some common features that we find on most common human faces :

  1. A dark eye region compared to upper-cheeks
  2. A bright nose bridge region compared to the eyes
  3. Some specific location of eyes, mouth, nose

The characteristics are called Haar Features. The feature extraction process will look like this :

在這裏插入圖片描述

In this example, the first feature measures the difference in intensity between the region of the eyes and a region across the upper cheeks. The feature value is simply computed by summing the pixels in the black area and subtracting the pixels in the white area.

在這裏插入圖片描述

Then, we apply this rectangle as a convolutional kernel, over our whole image. In order to be exhaustive, we should apply all possible dimensions and positions of each kernel. A simple 24*24 images would typically result in over 160’000 features, each made of a sum/subtraction of pixels values. It would computationally be impossible for live face detection. So, how do we speed up this process ?

  1. once the good region has been identified by a rectangle, it is useless to run the window over a completely different region of the image. This can be achieved by Adaboost.
  2. compute the rectangle features using the integral image principle, which is way faster. We’ll cover this in the next section.

Now that the features have been selected, we apply them on the set of training images using Adaboost classification, that combines a set of weak classifiers to create an accurate ensemble model. With 200 features (instead of 160’000 initially), an accuracy of 95% is achieved. The authors of the paper have selected 6’000 features.

Integral Image:
To quote an answer on quora - https://www.quora.com/How-integral-image-is-used-in-image-processing-and-how-improves-the-computation-time

Integral image is an image we get by cumulative addition of intensities on subsequent pixels in both horizontal and vertical axis.
In image processing, we generally rely on features specific to certain regions of the entire image. Hence, we need properties of those specific regions

Adaboost algorithm:

在這裏插入圖片描述

The above algorithm shows the steps taken to choose the appropriate classifiers

1.2 The result

one face zero face zero face
在這裏插入圖片描述 在這裏插入圖片描述 在這裏插入圖片描述

2. Histogram of Oriented Gradients (HOG) in Dlib

One of the most popular implement for face detection is offered by Dlib and uses a concept called Histogram of Oriented Gradients (HOG). This is an implementation of the original paper by Dalal and Triggs - https://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf

The model is built out of 5 HOG filters – front looking, left looking, right looking, front looking but rotated left, and a front looking but rotated right. The model comes embedded in the header(https://github.com/davisking/dlib/blob/master/dlib/image_processing/frontal_face_detector.h) file itself.

The dataset used for training, consists of 2825 images which are obtained from LFW dataset and manually annotated by Davis King, the author of Dlib. It can be downloaded from here - http://vis-www.cs.umass.edu/lfw/.

The idea behind HOG is to extract features into a vector, and feed it into a classification algorithm like a Support Vector Machine for example that will assess whether a face (or any object you train it to recognize actually) is present in a region or not.

The features extracted are the distribution (histograms) of directions of gradients (oriented gradients) of the image. Gradients are typically large around edges and corners and allow us to detect those regions.

In the original paper, the process was implemented for human body detection, and the detection chain was the following :

在這裏插入圖片描述
2.1 Compute tyhe HOG

The image is then divided into 8x8 cells to offer a compact representation and make our HOG more robust to noise. Then, we compute a HOG for each of those cells.

To estimate the direction of a gradient inside a region, we simply build a histogram among the 64 values of the gradient directions (8x8) and their magnitude (another 64 values) inside each region. The categories of the histogram correspond to angles of the gradient, from 0 to 180°. Ther are 9 categories overall : 0°, 20°, 40°… 160°.

We then calculate 2 information :

  1. Direction of the gradient
  2. Magnitude of the gradient

When we build the HOG, there are 3 subcases :

  1. The angle is smaller than 160° and not halfway between 2 classes. In such case, the angle will be added in the right category of the HOG
  2. The angle is smaller than 160° and exactly between 2 classes. In such case, we consider an equal contribution to the 2 nearest classes and split the magnitude in 2

在這裏插入圖片描述

  1. the angle is larger than 160°. In such case, we consider that the pixel contributed proportionally to 160° and to 0°.

在這裏插入圖片描述

The HOG looks like this for each 8x8 cell :

在這裏插入圖片描述

2.2 Block normalization

Finally, a 16x16 block can be applied in order to normalize the image and make it invariant to lighting for example. This is simply achieved by dividing each value of the HOG of size 8x8 by the L2-norm of the HOG of the 16x16 block that contains it, which is in fact a simple vector of length 9*4 = 36.

Finally, all the 36x1 vectors are concatenated into a large vector. And we are done ! We have our feature vector, on which we can train a soft SVM classifier.

在這裏插入圖片描述

2.3 The result

one face three faces seven faces
在這裏插入圖片描述 在這裏插入圖片描述 在這裏插入圖片描述

We can clearly see that the result of Histogram of Oriented Gradients using Dlib is better than Haar Cascade Classifiers using OpenCV there.

2- The code

2-1 Face recognition

Eigenfaces

import numpy as np
import pandas as pd
import os
import random
import imageio
import matplotlib.pyplot as plt
from collections import Counter
import  copy
%matplotlib inline
# 加上這兩行可以一次性輸出多個變量而不用print
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
# 顯示灰度圖
def showGray(img):
    plt.imshow(img, cmap='gray')
    plt.show()
# 讀取文件夾,返回文件地址列表
def readImage(foderName):
    addr = []
    for filename in os.listdir(foderName):
        addr.append(foderName + '/' + filename)
    return addr
# 標籤列表
nameList = [
    '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12',
    '13', '14', '15'
]
# 特徵列表
characteristic = [
    'centerlight', 'glasses', 'happy', 'leftlight', 'noglasses', 'normal', 'rightlight',
    'sad', 'sleepy', 'surprised', 'wink'
]
# 讀取圖片並劃分數據集爲訓練集和測試集
path = './project1-data-Recognition/subject'
def train_test_split(N):

    index = random.sample(range(0,11), N)
    temp = np.arange(11).tolist()
    index_ = list(set(index)^set(temp))

    x_train = []
    x_test = []
    y_train = []
    y_test = []

    for name in nameList:
        for character in [characteristic[i] for i in index]:
            src = path + name + '.' + character + '.pgm'
            img = imageio.imread(src)
            x_train.append(img)

        for character in [characteristic[i] for i in index_]:
            src = path + name + '.' + character + '.pgm'
            img = imageio.imread(src)
            x_test.append(img)

        for i in range(N):
            y_train.append(int(name))
        for j in range(N,11):
            y_test.append(int(name))
    return x_train, x_test, y_train, y_test
# 進行10次試驗取平均
N = 7 # 設置N值
try_nums = 10
x_trains = []
x_tests = []
for _ in range(try_nums):
    x_train, x_test, y_train, y_test = train_test_split(N)
    x_trains.append(x_train)
    x_tests.append(x_test)
# 畫出前4組人臉圖像
# 創建畫布和子圖對象
fig, axes = plt.subplots(4,N
                       ,figsize=(12,8)
                       ,subplot_kw = {"xticks":[],"yticks":[]} #不要顯示座標軸
                       )
#填充圖像
for i, ax in enumerate(axes.flat):
    ax.imshow(x_trains[0][i+4*N],cmap="gray") #選擇色彩的模式

在這裏插入圖片描述

# 進行特徵降採樣, 採樣間隔爲4
x_train_downs = copy.deepcopy(x_trains)
x_test_downs = copy.deepcopy(x_tests)
for i in range(try_nums):
    for j in range(len(x_train_downs[0])):
        x_train_downs[i][j] = x_trains[i][j][::2,::2]
    for j in range(len(x_test_downs[0])):
        x_test_downs[i][j] = x_tests[i][j][::2,::2]
print("============training data============")
print("降採樣特徵前:")
x_trains[0][0].shape
print("降採樣特徵後:")
x_train_downs[0][0].shape

print("==============test data==============")
print("降採樣特徵前:")
x_tests[0][0].shape
print("降採樣特徵後:")
x_test_downs[0][0].shape
============training data============
降採樣特徵前:

(231, 195)

降採樣特徵後:

(116, 98)

==============test data==============
降採樣特徵前:

(231, 195)

降採樣特徵後:

(116, 98)
# 圖像數據轉換特徵矩陣
train_lts = []
test_lts = []
for i in range(try_nums):
    x_train_down_mat = []
    x_test_down_mat = []
    for image in x_train_downs[i]:
        data = image.flatten()
        x_train_down_mat.append(data)
    train_lts.append(x_train_down_mat)

    for image in x_test_downs[i]:
        data = image.flatten()
        x_test_down_mat.append(data)
    test_lts.append(x_test_down_mat)

len(train_lts)
train_lts[1][1].shape
10

(11368,)
# 轉換爲numpy數組
x_train_arr = np.array(train_lts)
y_train_arr = np.array(y_train)
x_train_arr.shape

x_test_arr = np.array(test_lts)
y_test_arr = np.array(y_test)
x_test_arr.shape
(10, 105, 11368)

(10, 60, 11368)
# 平均臉
means = []
for i in range(try_nums):
    means.append(np.mean(x_train_arr[i], axis=0).reshape(x_train_downs[0][0].shape))
# 畫出平均臉
# 創建畫布和子圖對象
fig, axes = plt.subplots(1,10
                       ,figsize=(16,8)
                       ,subplot_kw = {"xticks":[],"yticks":[]} #不要顯示座標軸
                       )
#填充圖像
for i, ax in enumerate(axes.flat):
    ax.imshow(means[i],cmap="gray") #選擇色彩的模式

在這裏插入圖片描述

class PCA:
    def __init__(self):
        self.x_train_fit = None
        self.y_train_fit = None
        self.U = None
        self.S = None
        self.V = None

    def fit(self, x_train, y_train):
        self.x_train_fit = x_train
        self.y_train_fit = y_train
        return self

    # 數據標準化
    def Centralization(self, X):
        Centra = X - np.mean(self.x_train_fit, axis=0)
        return Centra

    def model(self):
        #定義一個新矩陣
        X_ = (1 / np.sqrt(len(self.Centralization(
            self.x_train_fit)))) * self.Centralization(self.x_train_fit)
        #進行奇異值分解
        self.U, self.S, self.V = np.linalg.svd(X_)

    def transform(self, X, K):
        X = self.Centralization(X)
        X_dunction = (((self.V).T[:, :K]).T).dot(X.T).T
        return X_dunction
pca = PCA()
resultTrain = []
resultTest = []
for i in range(try_nums):
    pca.fit(x_train_arr[i], y_train_arr)
    pca.model()
    X1 = []
    X2 = []
    for j in range(1,301):
        xTrain_i = pca.transform(x_train_arr[i], j)
        X1.append(xTrain_i)
        xTest_i = pca.transform(x_test_arr[i], j)
        X2.append(xTest_i)
    resultTrain.append(X1)
    resultTest.append(X2)
class KNN:
    def __init__(self, X_train, y_train, n_neighbors=3, p=2):
        """
        n_neighbors: 臨近點個數
        p: 距離度量
        """
        self.n = n_neighbors
        self.p = p
        self.X_train = X_train
        self.y_train = y_train

    def predict(self, X):
        # 取出n個點
        knn_list = []
        for i in range(self.n):
            dist = np.linalg.norm(X - self.X_train[i], ord=self.p)
            knn_list.append((dist, self.y_train[i]))

        for i in range(self.n, len(self.X_train)):
            max_index = knn_list.index(max(knn_list, key=lambda x: x[0]))
            dist = np.linalg.norm(X - self.X_train[i], ord=self.p)
            if knn_list[max_index][0] > dist:
                knn_list[max_index] = (dist, self.y_train[i])

        # 統計
        knn = [k[-1] for k in knn_list]
        count_pairs = Counter(knn)
        max_count = sorted(count_pairs.items(), key=lambda x: x[1])[-1][0]
        return max_count

    def score(self, X_test, y_test):
        right_count = 0
        n = 10
        for X, y in zip(X_test, y_test):
            label = self.predict(X)
            if label == y:
                right_count += 1
        return right_count / len(X_test)
# 用KNN分類器進行訓練
scores = []
for i in range(try_nums):
    scoreList = []
    for j in range(300):
        clf = KNN(resultTrain[i][j], y_train_arr)
        score = clf.score(resultTest[i][j], y_test_arr)
        scoreList.append(score)
    scores.append(scoreList)
# 計算平均誤分率
scoresMean = np.mean(scores, axis=0)
len(scoresMean)
errorMean = 1 - scoresMean
errorMean
300

array([0.78833333, 0.55833333, 0.37666667, 0.305     , 0.27333333,
       0.21833333, 0.19833333, 0.18333333, 0.15666667, 0.16333333,
       0.14333333, 0.13666667, 0.13333333, 0.14333333, 0.14166667,
       0.13333333, 0.13166667, 0.13      , 0.12833333, 0.12833333,
       0.135     , 0.125     , 0.12      , 0.12333333, 0.12166667,
       0.12833333, 0.13833333, 0.135     , 0.13      , 0.12833333,
       0.12833333, 0.12833333, 0.12666667, 0.12666667, 0.12833333,
       0.12833333, 0.12666667, 0.12166667, 0.12666667, 0.12333333,
       0.12666667, 0.12666667, 0.12666667, 0.125     , 0.12333333,
       0.12166667, 0.12166667, 0.11666667, 0.12166667, 0.12333333,
       0.12333333, 0.12833333, 0.12333333, 0.12666667, 0.12666667,
       0.12166667, 0.12      , 0.12166667, 0.12      , 0.12      ,
       0.12      , 0.11833333, 0.12666667, 0.12666667, 0.12666667,
       0.13      , 0.12666667, 0.12833333, 0.12666667, 0.12666667,
       0.12666667, 0.12166667, 0.12166667, 0.12166667, 0.12333333,
       0.12333333, 0.12333333, 0.12      , 0.12166667, 0.12      ,
       0.12      , 0.12      , 0.12166667, 0.12333333, 0.125     ,
       0.12      , 0.11833333, 0.11833333, 0.11833333, 0.12333333,
       0.13      , 0.13      , 0.13      , 0.12833333, 0.12666667,
       0.12666667, 0.12666667, 0.12833333, 0.12833333, 0.12833333,
       0.12666667, 0.125     , 0.12666667, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333,
       0.12833333, 0.12833333, 0.12833333, 0.12833333, 0.12833333])
# 畫平均誤分率曲線
# N = 3
plt.figure(figsize=(12,6))
epochs = range(300)

bestScore = np.max(scoresMean)
bestError = np.min(errorMean)

plt.plot(epochs, scoresMean, label='Score: %0.3f' % bestScore) 
plt.plot(epochs, errorMean, label='Error: %0.3f' % bestError)
plt.title('N = 3')
plt.legend()
Text(0.5, 1.0, 'N = 3')

在這裏插入圖片描述

# 畫平均誤分率曲線
# N = 5
plt.figure(figsize=(12,6))
epochs = range(300)

bestScore = np.max(scoresMean)
bestError = np.min(errorMean)

plt.plot(epochs, scoresMean, label='Score: %0.3f' % bestScore) 
plt.plot(epochs, errorMean, label='Error: %0.3f' % bestError)
plt.title('N = 5')
plt.legend()
Text(0.5, 1.0, 'N = 5')

在這裏插入圖片描述

# 畫平均誤分率曲線
# N = 7
plt.figure(figsize=(12,6))
epochs = range(300)

bestScore = np.max(scoresMean)
bestError = np.min(errorMean)

plt.plot(epochs, scoresMean, label='Score: %0.3f' % bestScore) 
plt.plot(epochs, errorMean, label='Error: %0.3f' % bestError)
plt.title('N = 7')
plt.legend()
Text(0.5, 1.0, 'N = 7')

在這裏插入圖片描述

Fisherfaces

# 由以上結果,我這裏選pca先降到300維
pca = PCA()
resultTrain = []
resultTest = []
for i in range(try_nums):
    pca.fit(x_train_arr[i], y_train_arr)
    pca.model()

    X1 = pca.transform(x_train_arr[i], 300)
    X2 = pca.transform(x_test_arr[i], 300)

    resultTrain.append(X1)
    resultTest.append(X2)
resultTrain[0].shape
resultTest[0].shape
(105, 300)

(60, 300)
def LDA(X, y):
    label_ = list(set(y))
    X_classify = {}
    for label in label_:
        X1 = np.array([X[i] for i in range(len(X)) if y[i] == label])
        X_classify[label] = X1

    miu = np.mean(X, axis=0)
    miu_classify = {}
    for label in label_:
        miu1 = np.mean(X_classify[label], axis=0)
        miu_classify[label] = miu1

    # St = np.dot((X - mju).T, X - mju)
    # 計算類內散度矩陣Sw
    Sw = np.zeros((len(miu), len(miu))) + 0.00001*np.random.rand(len(miu), len(miu))
    for i in label_:
        Sw += np.dot((X_classify[i] - miu_classify[i]).T,
                     X_classify[i] - miu_classify[i])

    #Sb = St-Sw
    # 計算類內散度矩陣Sb
    Sb = np.zeros((len(miu), len(miu)))
    for i in label_:
        Sb += len(X_classify[i]) * np.dot((miu_classify[i] - miu).reshape(
            (len(miu), 1)), (miu_classify[i] - miu).reshape((1, len(miu))))

    # 計算S_w^{-1}S_b的特徵值和特徵矩陣
    eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(Sw).dot(Sb))
    
    #對特徵值進行由高到低的排序
    eig_vecs = np.array([eig_vecs[:,i] for i in np.argsort(-eig_vals)])

    return eig_vecs
LDA(resultTrain[6], y_train_arr).shape
(300, 300)
# 計算準確率
scores = []
for i in range(try_nums):
    score = []
    for k in range(1,201):
        X = LDA(resultTrain[i], y_train_arr)[:,:k]
        X_1 = resultTrain[i].dot(X)
        X_2 = resultTest[i].dot(X)
        accu = 0
        for m in range(len(y_test_arr)):
            a = [np.linalg.norm(X_2[m,:] - X_1[j,:]) for j in range(len(y_train_arr))]
            min_dix = np.argmin(a)
            if y_train_arr[min_dix] == y_test_arr[m]:
                accu += 1
        score.append(accu/len(y_test_arr))
    scores.append(score)
len(scores[0])
200
# 計算平均誤分率
scoresMean = np.mean(scores, axis=0)
len(scoresMean)
errorMean = 1 - scoresMean
scoresMean
200

array([0.49166667, 0.57166667, 0.68333333, 0.70666667, 0.71      ,
       0.695     , 0.72333333, 0.71666667, 0.72166667, 0.75833333,
       0.76166667, 0.72      , 0.74666667, 0.765     , 0.755     ,
       0.78833333, 0.78833333, 0.78166667, 0.75333333, 0.775     ,
       0.79333333, 0.79833333, 0.78333333, 0.77      , 0.775     ,
       0.79      , 0.78666667, 0.81166667, 0.80833333, 0.79333333,
       0.805     , 0.79      , 0.77833333, 0.79166667, 0.8       ,
       0.82166667, 0.78333333, 0.79      , 0.79166667, 0.80166667,
       0.785     , 0.79666667, 0.795     , 0.80666667, 0.805     ,
       0.84333333, 0.82666667, 0.82333333, 0.79666667, 0.80166667,
       0.77333333, 0.81666667, 0.785     , 0.82333333, 0.82      ,
       0.84166667, 0.825     , 0.79166667, 0.795     , 0.795     ,
       0.82      , 0.81166667, 0.81833333, 0.79333333, 0.80833333,
       0.81666667, 0.78166667, 0.82166667, 0.80333333, 0.77333333,
       0.81      , 0.81833333, 0.79166667, 0.79      , 0.795     ,
       0.81666667, 0.83166667, 0.825     , 0.825     , 0.825     ,
       0.8       , 0.81333333, 0.83333333, 0.81666667, 0.815     ,
       0.77333333, 0.83      , 0.84333333, 0.80666667, 0.81666667,
       0.81833333, 0.80333333, 0.81      , 0.81166667, 0.81      ,
       0.805     , 0.835     , 0.84666667, 0.825     , 0.855     ,
       0.82166667, 0.80833333, 0.80666667, 0.80833333, 0.825     ,
       0.78666667, 0.815     , 0.80166667, 0.805     , 0.81333333,
       0.765     , 0.80166667, 0.78833333, 0.82166667, 0.77166667,
       0.815     , 0.82666667, 0.80666667, 0.82166667, 0.815     ,
       0.82833333, 0.80166667, 0.80666667, 0.805     , 0.80666667,
       0.805     , 0.82      , 0.80166667, 0.75666667, 0.805     ,
       0.81833333, 0.83666667, 0.80333333, 0.79833333, 0.8       ,
       0.79333333, 0.80166667, 0.82166667, 0.77333333, 0.805     ,
       0.785     , 0.79666667, 0.82      , 0.805     , 0.835     ,
       0.77166667, 0.825     , 0.78      , 0.82333333, 0.795     ,
       0.81      , 0.82      , 0.77833333, 0.805     , 0.82      ,
       0.795     , 0.805     , 0.755     , 0.79166667, 0.78333333,
       0.83833333, 0.81666667, 0.79666667, 0.80333333, 0.80666667,
       0.805     , 0.83      , 0.805     , 0.79833333, 0.80166667,
       0.81      , 0.80666667, 0.79333333, 0.81      , 0.75333333,
       0.82333333, 0.84      , 0.81833333, 0.8       , 0.79333333,
       0.81      , 0.81166667, 0.82      , 0.77833333, 0.81      ,
       0.82333333, 0.77833333, 0.80333333, 0.805     , 0.80166667,
       0.83333333, 0.80833333, 0.805     , 0.805     , 0.83333333,
       0.815     , 0.79666667, 0.82833333, 0.80833333, 0.85      ])
# 畫平均誤分率曲線
# N = 3
plt.figure(figsize=(12,6))
epochs = range(200)

bestScore = np.max(scoresMean)
bestError = np.min(errorMean)

plt.plot(epochs, scoresMean, label='Score: %0.3f' % bestScore) 
plt.plot(epochs, errorMean, label='Error: %0.3f' % bestError)
plt.title('N = 3')
plt.legend()
Text(0.5, 1.0, 'N = 3')

在這裏插入圖片描述

# 畫平均誤分率曲線
# N = 5
plt.figure(figsize=(12,6))
epochs = range(200)

bestScore = np.max(scoresMean)
bestError = np.min(errorMean)

plt.plot(epochs, scoresMean, label='Score: %0.3f' % bestScore) 
plt.plot(epochs, errorMean, label='Error: %0.3f' % bestError)
plt.title('N = 5')
plt.legend()
Text(0.5, 1.0, 'N = 5')

在這裏插入圖片描述

# 畫平均誤分率曲線
# N = 7
plt.figure(figsize=(12,6))
epochs = range(200)

bestScore = np.max(scoresMean)
bestError = np.min(errorMean)

plt.plot(epochs, scoresMean, label='Score: %0.3f' % bestScore) 
plt.plot(epochs, errorMean, label='Error: %0.3f' % bestError)
plt.title('N = 7')
plt.legend()
Text(0.5, 1.0, 'N = 7')

在這裏插入圖片描述

2-2 Face detection

import cv2
import dlib
from imutils import face_utils
import matplotlib.pyplot as plt
%matplotlib inline

Haar Cascade in detail - https://towardsdatascience.com/a-guide-to-face-detection-in-python-3eab0f6b9fc1

More Haar Features in OpenCV - https://github.com/opencv/opencv/tree/master/data/haarcascades

# Haar Cascade Classifiers using OpenCV
def detectHC(imgpath):
    # 加載級聯分類器文件
    cascPath = cv2.data.haarcascades+'haarcascade_frontalface_default.xml'
    faceCascade = cv2.CascadeClassifier(cascPath) # 定義級聯分類器

    # 讀取圖片
    frame = cv2.imread(imgpath)
    # 轉換通道模式
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 轉爲灰度圖
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 定義人臉檢測器進行檢測
    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(200, 200),
        flags=cv2.CASCADE_SCALE_IMAGE
    )

    # 打印檢測結果
    print(str(len(faces)) + ' faces can be detected!')
    
    # 在圖片上畫錨框
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)

    plt.imshow(frame)
    plt.show()
detectHC('./project1-data-Detection/1.jpg')
1 faces can be detected!

在這裏插入圖片描述

detectHC('./project1-data-Detection/2.jpg')
0 faces can be detected!

在這裏插入圖片描述

detectHC('./project1-data-Detection/3.jpg')
0 faces can be detected!

在這裏插入圖片描述

One of the most popular implement for face detection is offered by Dlib and uses a concept called Histogram of Oriented Gradients (HOG). This is an implementation of the original paper by Dalal and Triggs - https://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf

# Histogram of Oriented Gradients (HOG) in Dlib
def detectDlib(imgpath):
    # 讀取圖片
    frame = cv2.imread(imgpath)
    # 通道模式轉換
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 轉爲灰度圖
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 定義檢測器
    face_detect = dlib.get_frontal_face_detector()
    # 進行人臉檢測
    rects = face_detect(gray, 1)
    # 打印檢測結果
    print(str(len(rects)) + ' faces can be detected!')
    
    for (i, rect) in enumerate(rects):

        (x, y, w, h) = face_utils.rect_to_bb(rect)
        # 將檢測出的人臉可視化
        face = frame[y:y + w, x:x + h]
        plt.imshow(face)
        plt.show()
        # 在圖片上畫錨框
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
    plt.imshow(frame)
    plt.show()
detectDlib('./project1-data-Detection/1.jpg')
1 faces can be detected!

在這裏插入圖片描述

在這裏插入圖片描述

detectDlib('./project1-data-Detection/2.jpg')
3 faces can be detected!

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

rects = detectDlib('./project1-data-Detection/3.jpg')
7 faces can be detected!

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述


End

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章