Preprocessing

Histogram Equalization

Use cdf to transform intensity.

function eqimg = histogramequalization(img)
    maximum = round(max(img(:)));
    minimum = round(min(img(:)));
    counts = zeros(maximum-minimum+1, 1);
    
    [h, w] = size(img);
    
    for i = 1:h
        for j = 1:w
            counts(round(img(i, j)-minimum+1)) = counts((img(i, j)-minimum)+1) + 1;
        end
    end
    
    for i = 2:length(counts)
        counts(i) = counts(i) + counts(i-1);
    end
    
    eqimg = img;
    
    for i = 1:h
        for j = 1:w
            eqimg(i, j) = (counts(round(img(i, j)-minimum)+1)/(h*w)) * (maximum-minimum) + minimum;
        end
    end
    
end

Face Detection

Image Pyramid and Neural Network

Image Pyramid and Neural Network Image Pyramid and Neural Network Image Pyramid and Neural Network

Integral Image and AdaBoost

Use Viola-Jones’s method to get features and use AdaBoost to combine many weak classifiers into a strong classifier

Integral Image

function [img] = integralimage(img)
    
    [h, w] = size(img);
    
    for i = 2:h
        img(i, 1) = img(i-1, 1) + img(i, 1);
    end
    
    for i = 2:w
        img(1, i) = img(1, i-1) + img(1, i);
    end

    for i = 2:h
        for j = 2:w
            img(i, j) = img(i-1, j) + img(i, j-1) - img(i-1, j-1) + img(i, j);
        end
    end
    
end

AdaBoost

See AdaBoost and the Super Bowl of Classifiers A Tutorial Introduction to Adaptive Boosting

$n$ weak classifiers $K=[K_1, K_2, \cdots, K_n]$ and their weights $\alpha=[\alpha_1, \alpha_2, \cdots, \alpha_n]$

Adaboost trains a strong classifier: $C=sgn(\displaystyle\sum_{i}\alpha_i*K_i)$

Weights array $W=[w_1, w_2, \cdots, w_m]$ for $m$ training images.

The algorithm is as following:

W = ones(m)

while len(K) > 0:
    choose K_i with minimum W_e    
    alpha_i = 1/2*ln((W-W_e)/W_e)
    for w in W_e:
        w *= ((W-W_e)/W_e)^(1/2)
    for w in W_c:
        w *= ((W-W_c)/W_c)^(1/2)
    remove K_i from K

Face Recognition using eigenface

Flatten

Flatten each image into 1D vector $[X_1, X_2, \cdots, X_m]$.

PCA

Calculate $\overline{X}=\frac{1}{m}\displaystyle\sum_i{X_i}$.

Calculate covariance matrix $Cov$ for $[X_1-\overline{X}, \cdots, X_m-\overline{X}]$.

Calculate $eigValues=[\lambda_1, \cdots, \lambda_t]$ and related eigVectors for $Cov$.

Calculate coefficients for images by multiplying eigVectors $[g_1, \cdots, g_t]$.

Calculate eigFace for training images: $\overline{X} + \displaystyle\sum_i{g_i*eigV_i}$

Get nearest Face

For a test face $X_{test}$

Calculate eigFace of $X_{test}$ and use nearest neighbor.

Implementation

The following is my implementation of the algorithm.

class FaceRecognizer:
	def __init__(self):
		pass

	def train(self, trainSet, labels):
		imgLen = trainSet.shape[1]
		avg = np.average(trainSet, axis=0)
		trainSet = trainSet.astype(np.float64)
		trainSet -= np.repeat(np.reshape(avg, (1, imgLen)), len(trainSet), 0)
		cov = np.matmul(trainSet, trainSet.transpose())
		eigValues, eigVectors = np.linalg.eig(cov)
		max_arg = eigValues.argsort()[::-1]
		eigValues = eigValues[max_arg[:20]]
		eigVectors = eigVectors[:][max_arg[:20]].transpose()
		self.eigValues = eigValues
		self.eigVectors = eigVectors
		self.coefficients = np.matmul(trainSet.transpose(), eigVectors)
		self.labels = labels
		self.avg = avg
		self.imLen = imgLen

	def recognize(self, img):
		img = np.reshape(img, (1, self.imLen)) - self.avg
		coef = np.matmul(img, self.eigVectors)
		diff = self.coefficients - np.repeat(coef, len(self.coefficients), 0)
		diff = np.sum(diff ** 2, 1)
		idx = np.argsort(diff)[0]
		return self.labels[idx]

	def getEigVecs(self):
		return self.eigVectors

	def getAvg(self):
		return self.avg

	def getCoefficients(self):
		return self.coefficients

Test code that uses the recognizer:

import numpy as np
import cv2
from PIL import Image
from matplotlib import pyplot as plt
import os
import face_recognizer

path_train = './Data/Yale faces/Cropped'

data = []
labels = []

shape = (0, 0)
i = 0
for f in os.listdir(path_train):
	if not f.startswith('.') and f.endswith('.pgm'):
		img = Image.open(os.path.join(path_train, f))
		img = np.array(img)
		if img.ndim == 3:
			img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
		shape = img.shape
		data.append(img.flatten())
		labels.append(f.split('.')[0])
		i += 1

data = np.array(data)

recognizer = face_recognizer.FaceRecognizer()

recognizer.train(data, labels)

eigVecs = recognizer.getCoefficients()

_, plts = plt.subplots(5, 5)

eigImgs = []
for i, vec in enumerate(eigVecs.transpose()):
	eigVec = np.real(vec)
	miin = np.min(eigVec)
	maax = np.max(eigVec)
	eigVec = 255 * (eigVec - miin) / (maax - miin)
	eigImg = eigVec.astype(np.int32).reshape(shape)
	plts[i / 5][i % 5].imshow(eigImg, 'gray')
	eigImgs.append(eigImg)

plts[4][0].imshow(recognizer.getAvg().reshape(shape), 'gray')

plt.show()

Eigenface