DAY 96-100 DAYS MLCODE: Classification using HOG

My Tech World

DAY 96-100 DAYS MLCODE: Classification using HOG

February 16, 2019 100-Days-Of-ML-Code blog 0

In the previous blog, we discussed HOG, in this blog we’ll try to see HOG in action. Let’s develop a classifier using HOG.

Let’s download the faces from the Labeled Faces in the Wild dataset, which we can downloaded by Scikit-Learn:

from sklearn.datasets import fetch_lfw_people
face_images = fetch_lfw_people()
good_patches = face_images.images
good_patches.shape

Now download some none face images. We can take input images, and extract thumbnails from images at a variety of scales. We can use some of the images from Scikit-Image and Scikit-Learn’s PatchExtractor

from skimage import data, transform

non_face_img = ['camera', 'text', 'coins', 'moon',
               'page', 'clock', 'immunohistochemistry',
               'chelsea', 'coffee', 'hubble_deep_field']
negative_images = [color.rgb2gray(getattr(data, name)())
          for name in non_face_img]

Let’s review the data which we prepared above.

fig, ax = plt.subplots(6, 10)
for i, axi in enumerate(ax.flat):
    axi.imshow(negative_patches[500 * i], cmap='gray')
    axi.axis('off')
None-face images
Non-face images

Let’s combine them and compute HOG features. This step takes a little while, because the HOG features involve a nontrivial computation for each image.

from itertools import chain
X_train = np.array([feature.hog(im)
                    for im in chain(good_patches,
                                    bad_patches)])
y_train = np.zeros(X_train.shape[0])
y_train[:good_patches.shape[0]] = 1

Train Model

For a high-dimensional binary classification task, a Linear support vector machine is a good choice. Let’s use Scikit-Learn’s,LinearSVC because in comparison to itSVC often has better scaling for a large number of samples.

First, though, let’s use a simple Gaussian naive Bayes to get a quick baseline

from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import cross_val_score
cross_val_score(GaussianNB(), X_train, y_train)

Output:

array([0.94677677, 0.91423218, 0.94073971])

We can see that even our simple Gaussian is able to provide the 91% accuracy.

Let’s try the support vector machine, with a grid search over a few choices of the C parameter.

from sklearn.svm import LinearSVC
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(LinearSVC(), {'C': [1.0, 2.0, 4.0, 8.0]})
grid.fit(X_train, y_train)
grid.best_score_

Output : 0.9863530173709898

We can see the score reached at 98% with C = 2.

Let’s create and re-train the model with best estimator parameters

model = grid.best_estimator_
model.fit(X_train, y_train)

Output: LinearSVC(C=2.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, loss=’squared_hinge’, max_iter=1000, multi_class=’ovr’, penalty=’l2′, random_state=None, tol=0.0001, verbose=0)

Test the new Model

We are going to use the below image to see whether model can predict or not

Test image

Now read the image from internet and convert into gray scale.

!wget -O image_n1.jpg https://img.etimg.com/thumb/msid-57927105,width-300,imgsize-43611,resizemode-4/virat-kohli-hikes-endorsement-fee-to-rs-5-crore/day-highest-among-indian-celebrities.jpg

from skimage import io
image_1 = io.imread(‘image_n1.jpg’)
test_image = image_1 #skimage.data.astronaut()
test_image = skimage.color.rgb2gray(test_image)
test_image = skimage.transform.rescale(test_image, 0.5)
test_image = test_image[:160, 40:180]

plt.imshow(test_image, cmap=’gray’)
plt.axis(‘off’);

We can take these HOG-featured patches and use our model to evaluate whether each patch contains a face

labels = model.predict(patches_hog)
labels.sum()

Output 11

Let’s now draw the rectangle

fig, ax = plt.subplots()
ax.imshow(test_image, cmap=’gray’)
ax.axis(‘off’)

Ni, Nj = positive_patches[0].shape
indices = np.array(indices)

for i, j in indices[labels == 1]:
ax.add_patch(plt.Rectangle((j, i), Nj, Ni, edgecolor=’red’,
alpha=0.3, lw=2, facecolor=’none’))

Output:

Output using HOG
Output of the model

In summary, we can see that we are able to detect the faces using very few lines of code. Not a bad idea and it is working as expected. You can find the entire code here.