#### Face Recognition Using Eigen Faces

H
```{
"nbformat": 4,
"nbformat_minor": 0,
"colab": {
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"source": [
"Used the approach mentioned in the research paper by Matthew Turk and Alex Pentland, for face recognition using Eigenfaces. The algorithm was implemented using basic matrix algebra and numpy. <br>\n",
"Link to the research paper: https://ieeexplore.ieee.org/document/139758 <br>\n",
],
"id": "92bQUTh4CPXg"
}
},
{
"cell_type": "code",
"execution_count": null,
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "vHxEROwMLXOM",
"outputId": "7c9599a0-aefb-449e-c482-dee75bed4570"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Requirement already satisfied: opencv-python in /usr/local/lib/python3.7/dist-packages (4.6.0.66)\n",
"Requirement already satisfied: numpy>=1.14.5 in /usr/local/lib/python3.7/dist-packages (from opencv-python) (1.21.6)\n"
]
}
],
"source": [
"!pip install opencv-python"
]
},
{
"cell_type": "code",
"source": [
"# taken from this StackOverflow answer: https://stackoverflow.com/a/39225039\n",
"import requests\n",
"\n",
"\n",
"    session = requests.Session()\n",
"\n",
"    response = session.get(URL, params = { 'id' : id }, stream = True)\n",
"    token = get_confirm_token(response)\n",
"\n",
"    if token:\n",
"        params = { 'id' : id, 'confirm' : token }\n",
"        response = session.get(URL, params = params, stream = True)\n",
"\n",
"    save_response_content(response, destination)    \n",
"\n",
"def get_confirm_token(response):\n",
"    for key, value in response.cookies.items():\n",
"            return value\n",
"\n",
"    return None\n",
"\n",
"def save_response_content(response, destination):\n",
"    CHUNK_SIZE = 32768\n",
"\n",
"    with open(destination, \"wb\") as f:\n",
"        for chunk in response.iter_content(CHUNK_SIZE):\n",
"            if chunk: # filter out keep-alive new chunks\n",
"                f.write(chunk)"
],
"id": "RV2ZZg9aLbBA"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"The dataset used was the AT&T dataset, where 10 different images of 40 distinct subjects were given. The 10 images of the same person were taken under varying circumstances, like different lighting, facial expressions and facial accessories. <br>\n",
"\n",
"We took two images of each of the 40 people for testing. The model was trained on 8 images of the first 20 people. We did this so that we can calculate the accuracy for people both inside and outside our training set. <br>\n",
"\n",
"On running the code, train_small.zip, test1.zip and test2.zip will appear in the contents folder. These signify the following:\n",
"<ol>\n",
"<li>train_small: training dataset, contains 8 images of 20 different people.</li><li>test1.zip: testing dataset, contains 2 images all people from the training dataset.</li>\n",
"<li>test2.zip: testing dataset, consisting of 2 images of 20 new people whose images weren't present in the training dataset.</li>\n"
],
"id": "NqQ4B8X5DoeI"
}
},
{
"cell_type": "code",
"source": [
"file_id = '1Z9evWwUK4nTpARz67ZWraNe5sX2MNcFx'\n",
"destination = '/content/dataset.zip'\n",
"\n",
"!unzip -q dataset.zip\n",
"!rm -rf dataset.zip"
],
"id": "Ktar_dpcWBHa"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"test_file_id_1 = '1bIr_ikTxGuuZnJulykXeZz04pyb27S3f'\n",
"test_destination_1 = '/content/test1.zip'\n",
"\n",
"!unzip -q test1.zip\n",
"!rm -rf test1.zip"
],
"id": "yM27R6wHV_iu"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"test_file_id_2 = '1Kj0QsxJ1m0n0UCPiaFskskUhM7fvxqS4'\n",
"test_destination_2 = '/content/test2.zip'\n",
"\n",
"!unzip -q test2.zip\n",
"!rm -rf test2.zip"
],
"id": "Tz7GFtJqHe4M"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# All images are supposed to be the same size, say, N*L\n",
"IMAGE_DIR = \"/content/train_small\""
],
"id": "0XTxubQAL-dq"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# importing necessary libraries\n",
"\n",
"import os\n",
"import numpy as np\n",
"import cv2\n",
"import matplotlib.pyplot as plt\n",
"import fnmatch\n",
"import re"
],
"id": "sSAMwOfmMIfW"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def getClassFromName(fileName,lastSubdir=True):\n",
"        if lastSubdir:\n",
"            name = os.path.basename(os.path.dirname(fileName))\n",
"        else:\n",
"            name = os.path.basename(fileName)\n",
"        mat = re.match(\".*(\\d+).*\", name)\n",
"        if mat != None:\n",
"            return int(mat.group(1))\n",
"        else:\n",
"            return name.__hash__()"
],
"id": "IeBCGIscNHwz"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"image_names = []\n",
"image_dictionary = []\n",
"\n",
"image_1D = []\n",
"for root, dirnames, filenames in os.walk(IMAGE_DIR):\n",
"    for filename in fnmatch.filter(filenames, \"*.*\"):\n",
"        image_names.append(os.path.join(root, filename))\n",
"for idx,image_name in enumerate(image_names):\n",
"    if idx == 0:\n",
"        imgShape = img.shape\n",
"        vector_matrix = np.zeros((imgShape[0]*imgShape[1], len(image_names)),dtype=np.float64)\n",
"    image_dictionary.append((image_name,img,getClassFromName(image_name)))\n",
"    image_1D.append(img.flatten())"
],
"id": "PWqng3a_YB9P"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# print(image_1D)\n",
"print(len(image_1D))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "OH9-dPHwMkM6",
"outputId": "2bcfed51-a8de-496b-d60b-66988c834bb7"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"160\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Training Methodology:\n",
"<ol>\n",
"<li>We start by grayscaling the images and converting them into matrices of shape 112x92.</li><li>\n",
"Now each of these matrices was flattened and converted into a matrix of shape 10304x1. (Here 10304 comes from 112*92). All these vectors were stacked row wise into a single matrix (image_1D in our code).</li><li>\n",
"Now we normalize each row of this matrix by subtracting the row wise mean from each element of the corresponding row. This new matrix will be called AT, and the transpose of this matrix will be called A.</li><li>\n",
"Next we calculate the covariance matrix by doing ATxA.</li><li>\n",
"Next we calculate the eigenvalues and eigenvectors of the covariance matrix using the linalg.eig of numpy. </li><li>\n",
"Next step is dimensionality reduction. We choose a number K, and choose K eigen vectors corresponding to the K largest eigenvalues. </li><li>\n",
"Now we calculated the normalized training faces (face-average face) and represented each normalized face as a linear combination of the eigenvectors obtained in step 6. These w vectors were calculated using the np.linalg.lstsq function of numpy.\n",
"</li><li>\n",
"After calculating the weights (w vectors), we stacked those vectors </li>\n"
],
"id": "S8sblmfPFuIC"
}
},
{
"cell_type": "markdown",
"source": [
"Calculating the normalized image vectors."
],
"id": "_fTlX3dsZ5AG"
}
},
{
"cell_type": "code",
"source": [
"# We normalize each row of this matrix by subtracting the row wise mean from each element of the corresponding row. \n",
"# This new matrix will be called AT\n",
"mean = []\n",
"a_transpose_norm = []\n",
"for i in range(len(image_1D[0])):\n",
"  mean.append(0)\n",
"\n",
"  for j in range(len(image_1D)):\n",
"    mean[i] += image_1D[j][i]/len(image_1D)\n",
"    # print(sum)\n",
"\n",
"for i in range(len(image_1D)):\n",
"  a_transpose_norm.append([])\n",
"  for j in range(len(mean)):\n",
"    a_transpose_norm[i].append(image_1D[i][j] - mean[j])\n",
"    # print(a_transpose_norm)\n",
"\n",
"# print(len(a_transpose_norm))"
],
"id": "2S6cKxQQNZoj"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# The transpose of the matrix computed above will be called A.\n",
"a_norm = np.transpose(a_transpose_norm)  #A\n",
"len(a_norm)"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Ddx33GkhZX8j",
"outputId": "16765a4f-d120-4079-cbe9-ebf60aabce41"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"10304"
]
},
"execution_count": 15
}
]
},
{
"cell_type": "markdown",
"source": [
"Calculating eigenvectors and eigenvalues of the covariance matrix formed by the image vectors."
],
"id": "t0rjkbbTaQi9"
}
},
{
"cell_type": "code",
"source": [
"# We calculate the covariance matrix by doing ATxA.\n",
"cov_matrix = np.cov(a_transpose_norm) # At*A\n",
"# print(cov_matrix)\n",
"len(cov_matrix[0])"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "6yWV1oy4R6ZO",
"outputId": "b3d9a20e-009e-4fb0-f16d-fa11f73b168c"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"160"
]
},
"execution_count": 16
}
]
},
{
"cell_type": "code",
"source": [
"eigen = np.linalg.eig(cov_matrix) # returns eigen values and then all eigen vectors\n",
"# for i in range(len(eigen)):\n",
"#   print(eigen[i])\n",
"v_eigenvalues=eigen[0]\n",
"v=np.transpose(eigen[1])\n",
"# print(v_eigenvalues)\n",
"# print(v)\n",
"# print(len(v), len(v[0]))\n"
],
"id": "s4jQdXEbXq2B"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"u_transpose = []\n",
"for i in range(len(v)):\n",
"  array = np.matmul(a_norm,v[i])\n",
"  u_transpose.append(array)\n",
"u=np.transpose(u_transpose)\n",
"# print(len(u),len(u[0]))\n",
"print(len(u), len(u[0]))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "iOa48rbZcr9n",
"outputId": "71bcb11d-0695-44e1-b331-ed69cee814c7"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"10304 160\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"eigen_values = eigen[0]\n",
"eigen_vectors=eigen[1]\n",
"# print(eigen_values)\n",
"eigen_d = {}\n",
"for i in range(len(eigen_values)):\n",
"  eigen_d[eigen_values[i]]=i\n",
"# eigen_d"
],
"id": "TH1PFX1ysqDl"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Selecting the K eigenvectors of covariance matrix corresponding to the K largest eigenvalues. "
],
"id": "iEraN5okaqkv"
}
},
{
"cell_type": "code",
"source": [
"k=12"
],
"id": "nEP902JtbGHS"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# sorting the dictionary of eigenvalues to get the corresponding eigenvectors.\n",
"from collections import OrderedDict\n",
"dict1 = OrderedDict(sorted(eigen_d.items(),reverse=True))\n",
"dict2=dict(dict1)\n",
"print(dict2)"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "nFrNOHuRvpqK",
"outputId": "88b6fe0e-f8cb-4e00-80db-c52a7b5d881b"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"{43219.953977553596: 0, 18749.895990890815: 1, 17942.155464146246: 2, 12061.802455045403: 3, 10489.25912953686: 4, 8066.724722559026: 5, 7297.85172164008: 6, 6261.016588366359: 7, 5873.753178029104: 8, 4420.5004066534: 9, 3826.304473465676: 10, 3579.8886501814827: 11, 3112.701941552233: 12, 2932.3449009364517: 13, 2747.3196034473535: 14, 2487.396345846331: 15, 2411.0446487988524: 16, 2252.6641238208167: 17, 2074.7096367875374: 18, 1989.9475765463246: 19, 1928.8795510110008: 20, 1773.305425328178: 21, 1676.8247434736688: 22, 1640.8845693566923: 23, 1586.0134088610828: 24, 1384.3119343572707: 25, 1360.5249845839646: 26, 1272.8354997100732: 27, 1171.4911399813118: 28, 1150.5295704016391: 29, 1117.2277311946657: 30, 1066.7345849297926: 31, 1027.8242127649535: 32, 1000.5604997800493: 33, 957.4881339639342: 34, 932.1908536264845: 35, 890.6505933876211: 36, 867.9216091629972: 38, 833.6071838643115: 39, 806.8325487486294: 40, 774.5620675914377: 41, 758.6272156532845: 42, 738.4342113595159: 43, 714.5399164439951: 44, 682.7055539009281: 46, 680.9252271100078: 47, 673.9283018815898: 48, 658.4301569913085: 45, 625.0816864277112: 49, 617.5582835272636: 50, 606.4179117332367: 51, 574.3310372756353: 53, 569.9325407493129: 52, 556.968211979823: 54, 548.371195855361: 55, 541.394394333996: 56, 517.6264019518915: 58, 516.5821198500923: 57, 500.04350432768587: 59, 482.81038227024146: 60, 474.40612112126905: 61, 472.91907873668464: 62, 463.37362069900644: 63, 448.87411947393264: 64, 445.1195525159666: 65, 433.8822394567646: 66, 424.9545193027636: 67, 414.34625398368985: 73, 410.44103052260715: 72, 399.7720057166255: 74, 392.1543734446897: 75, 387.79362525258114: 76, 374.2368664887361: 79, 371.49945348490684: 80, 366.1104550707202: 81, 362.76582599959437: 83, 362.07916777129213: 82, 352.7149467318006: 86, 347.6629266571733: 87, 344.4517149718263: 88, 338.56891140470464: 89, 326.7105220744234: 94, 326.25054239097585: 95, 317.973905297458: 99, 315.61948544607054: 100, 312.15439105645754: 109, 308.5046455356127: 101, 302.55416730618424: 110, 298.5400400481408: 111, 292.27487160513783: 112, 288.8823139316889: 113, 285.0435271976845: 114, 282.9772519873982: 115, 277.64467614646475: 117, 273.7020381676069: 118, 269.5357634357952: 142, 265.9471151508216: 119, 261.3862164259361: 120, 259.8671420930868: 126, 257.6130828977115: 125, 254.21906797290566: 131, 250.616479699577: 128, 246.06438730855305: 127, 240.00699924404051: 129, 234.8180913874552: 130, 232.7549425732958: 141, 230.7956380602637: 143, 226.5311551599993: 159, 223.75397178988626: 153, 221.54950660799236: 152, 219.43463583127505: 158, 217.41411147378702: 151, 215.48480958242658: 150, 211.49682062225486: 154, 209.55479232153124: 157, 208.1694532219256: 156, 206.43451832745535: 155, 200.65013822053376: 144, 199.90465610231152: 145, 197.0978066449791: 140, 195.18560080202585: 147, 190.91520321768897: 146, 189.6685050111701: 137, 185.6900961024561: 139, 182.2508248568398: 136, 178.73701239142918: 135, 174.5908773381799: 132, 169.827660924428: 124, 166.7766873707503: 134, 165.7343487334624: 138, 163.50086445520705: 133, 161.8161444605663: 149, 159.93509949384642: 123, 157.84439541824133: 121, 155.2947155213594: 148, 154.80023084350475: 122, 150.43467043710345: 116, 147.1590447262029: 108, 140.48035960506212: 107, 138.73007592494284: 106, 137.8886194586964: 105, 133.96609468111802: 104, 133.32671443969662: 103, 131.35871093197667: 102, 126.39832659543461: 98, 123.8572162371065: 97, 120.39979904790052: 96, 119.33111585528107: 93, 117.61534130912757: 92, 115.93856715938144: 91, 109.54104484025125: 90, 108.20582883113228: 85, 101.43665329843098: 84, 89.47901931450252: 78, 84.06012945411771: 77, 70.50578026422139: 71, 65.59787544247587: 70, 62.77453678940503: 69, 59.32778617838623: 68, -5.107739735450283e-13: 37}\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# indexes of of k maximum eigenvalues\n",
"index_list=[]\n",
"for e in dict2:\n",
"  if(len(index_list)>=k):\n",
"    break\n",
"  index_list.append(dict2[e])\n",
"print(index_list)"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Cbg1ul5QxPI0",
"outputId": "d7a6ecaf-b420-40ae-ca61-f486f94abc75"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# eigenvectors of k maximum eigenvalues\n",
"u_k=[]\n",
"for i in index_list:\n",
"  u_k.append(u_transpose[i])\n",
"print(u_k)"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "qieh14Bw0eFk",
"outputId": "db0bc194-6afe-47ef-be65-057354b46ccc"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[array([-250.34987268, -246.96739775, -251.03150872, ...,   62.66394197,\n",
"         42.95102603,   -7.43283506]), array([-293.03400587, -296.61765524, -294.39034777, ...,  -50.55568765,\n",
"        -45.94985846,  -50.66399445]), array([ 69.73691919,  64.22732671,  68.583571  , ..., -41.61421501,\n",
"       -40.95085605, -38.69027747]), array([ 15.24047245,  19.31637724,  22.9986019 , ..., -81.3522821 ,\n",
"       -68.21885398, -73.1093675 ]), array([   7.04373461,    4.56640216,    2.24472334, ..., -102.02376868,\n",
"        -80.93066914,  -59.14922928]), array([-64.63035609, -68.56599373, -60.92922784, ...,  97.30812891,\n",
"        83.50398642,  56.29972771]), array([-73.39842816, -75.85858873, -75.10925541, ..., -21.30720511,\n",
"       -25.49241544,   5.10502217]), array([  76.33460672,   78.27079323,   83.86525799, ..., -100.27234286,\n",
"        -77.988847  ,  -61.0207666 ]), array([-103.25654954, -100.23979122,  -96.30983044, ...,  -37.3388256 ,\n",
"        -49.91948021,  -28.46092446]), array([-62.26684061, -59.45034204, -62.54270953, ..., 151.8902004 ,\n",
"       121.29818377, 111.59794073]), array([ -92.97767444,  -95.5290902 ,  -91.18621931, ..., -113.1381992 ,\n",
"        -91.31555489,  -88.30228713]), array([-74.61218527, -70.83391408, -71.92315934, ...,  52.7331185 ,\n",
"        48.02889301,  55.92254778])]\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Plotting the mean vector."
],
"id": "HvDlF6TucQzE"
}
},
{
"cell_type": "code",
"source": [
"fig,axarr = plt.subplots()\n",
"axarr.set_title(\" plot_mean_vector\")\n",
"avg_image = np.reshape(mean, (imgShape))\n",
"axarr.imshow(avg_image, cmap=plt.cm.gray)"
],
"colab": {
"base_uri": "https://localhost:8080/",
"height": 298
},
"outputId": "0b25ab2f-107b-459d-a33e-9665fe76249b"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f3182920b10>"
]
},
"execution_count": 24
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"source": [
"Plotting the k eigenfaces."
],
"id": "mFsvoKGpce9C"
}
},
{
"cell_type": "code",
"source": [
"for i in range(k):\n",
"  fig,axarr = plt.subplots()\n",
"  axarr.set_title(\" plot_eigen_face_\"+str(i+1))\n",
"  avg_image = np.reshape(u_k[i], (imgShape))\n",
"  axarr.imshow(avg_image, cmap=plt.cm.gray)"
],
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1000
},
"id": "iL9YmhBp51Vk",
"outputId": "0067fde8-2220-4363-e4bc-42a9b836ddfd"
},
"execution_count": null,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"source": [
"Projecting the image vector onto the eigenvector space for the training images."
],
"id": "Hg8aa-AKdPQQ"
}
},
{
"cell_type": "code",
"source": [
"#storing the weights of each training image in an array.\n",
"w_array=[]\n",
"for i in range(len(cov_matrix[0])):\n",
"  w=np.linalg.lstsq(np.transpose(u_k),np.transpose(a_transpose_norm[i]))\n",
"  w_array.append(w[0])\n",
"print(len(w_array), len(w_array[0]))\n",
"# w_array"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "gnVhNr3ED62j",
"outputId": "548970bc-943c-43f1-ce3e-7f04f10631fc"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:4: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.\n",
"To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.\n",
"  after removing the cwd from sys.path.\n"
]
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"160 12\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"**Testing the algorithm.**\n",
"<ol>\n",
"<li>\n",
"We start by gray scaling and resizing the test image to fit our algorithm.\n",
"Next, we normalize the test image by subtracting the mean face from our unknown face. </li><li>\n",
"This normalized vector is projected into the eigenspace to obtain the linear combination of the eigenfaces.\n",
"</li><li>\n",
"We stack the w vectors obtained as follows:\n",
"</li><li>\n",
"We take the stacked w this vector and subtract it from the training images to get the minimum distance between the training vectors and testing vectors.\n",
"</li><li>\n",
"If this error comes out to be lower than the set threshold, then we find which face it is most similar to in the training images, else we report that the test image does not match with any image in the training set.\n",
"</li>"
],
"id": "zy3kFuSheBcb"
}
},
{
"cell_type": "markdown",
"source": [
"Run this after uploading a suitable PGM file to the colab runtime."
],
"id": "kdmdpVkeeafN"
}
},
{
"cell_type": "code",
"source": [
"# calculating the k weights of the testing image.\n",
"test_input_dir = '/content/test1/2.10.pgm'\n",
"\n",
"img2 = cv2.resize(img, (92,112)).flatten()\n",
"test_norm = []\n",
"for j in range(len(mean)):\n",
"    test_norm.append(img2[j] - mean[j])\n",
"    \n",
"w_test = np.linalg.lstsq(np.transpose(u_k),np.transpose(test_norm))\n",
"# w[0]\n",
"w_test[0]"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "v7sytPPUHcxG",
"outputId": "afc8290b-deea-4d1e-ace1-bdb5fa32ebec"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stderr",
"text": [
"/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:10: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.\n",
"To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.\n",
"  # Remove the CWD from sys.path while we load stuff.\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([ 0.06458022,  0.03106545, -0.00325797, -0.05024619,  0.07550252,\n",
"       -0.03153704,  0.07448419,  0.07458258,  0.11583648,  0.18621974,\n",
"        0.04560699,  0.08938435])"
]
},
"execution_count": 27
}
]
},
{
"cell_type": "markdown",
"source": [
"Generating the output image by the weigted average of all eigenvectors. "
],
"id": "7TGiEstKesrP"
}
},
{
"cell_type": "code",
"source": [
"test_out = np.zeros([10304,1])\n",
"# print(len(test_out),len(test_out[0]) )\n",
"# print(len(eigen_vectors) , len(eigen_vectors[1]))\n",
"\n",
"for i in range(10304):\n",
"  for j in range(k):\n",
"    test_out[i]+=u_k[j][i]*w_test[0][j]\n",
"  # temp = np.multiply(eigen_vectors[i], w[0][i])\n",
"\n",
"test_out\n",
"# print(len(test_out) , len(test_out[1]))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Hj2uRB2ke4Vy",
"outputId": "cc43eb03-917e-4e39-8efa-01106529b1f7"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([[-57.93336317],\n",
"       [-57.019568  ],\n",
"       [-57.37504091],\n",
"       ...,\n",
"       [ 10.37543204],\n",
"       [  5.38218141],\n",
"       [  9.78964487]])"
]
},
"execution_count": 28
}
]
},
{
"cell_type": "code",
"source": [
"fig,axarr = plt.subplots()\n",
"axarr.set_title(\" plot_input_test_vector\")\n",
"avg_image = np.reshape(img2, (imgShape))\n",
"axarr.imshow(avg_image, cmap=plt.cm.gray)"
],
"colab": {
"base_uri": "https://localhost:8080/",
"height": 298
},
"id": "Hniwm1aO3HFG",
"outputId": "36ca6488-c6e8-42da-93e5-23926e5cbc7b"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f3181ee8090>"
]
},
"execution_count": 29
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"source": [
"fig,axarr = plt.subplots()\n",
"axarr.set_title(\" plot_generated_output_vector\")\n",
"avg_image = np.reshape(test_out, (imgShape))\n",
"axarr.imshow(avg_image, cmap=plt.cm.gray)"
],
"id": "1GzhX1NCaVa_",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 298
},
"outputId": "e288cc3f-ece6-4978-efc2-bae1c5376ac5"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f3181e4b090>"
]
},
"execution_count": 30
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"source": [
"Calculating error and finding out the most similar face in the training dataset that matches the given test image."
],
"id": "dDLZZEzBgTcL"
}
},
{
"cell_type": "code",
"source": [
"err_list=[]\n",
"err_ind=-1\n",
"for i in range(len(w_array)):\n",
"  err_list.append(np.linalg.norm(w_array[i]-w_test[0]))\n",
"print(err_list)\n",
"for i in range(len(err_list)):\n",
"  if err_list[i]==min(err_list):\n",
"    err_ind = i\n",
"    print(err_ind)\n",
"print(min(err_list), max(err_list))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Nl3S2qqY6V6V",
"outputId": "4ac6401a-fda2-4fe1-a05c-26417ffaefc2"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[0.34400506725215224, 0.4086184422732713, 0.3390396914525325, 0.350996578240961, 0.46533988720905706, 0.40559758059022627, 0.40332782853805116, 0.34467609524318865, 0.3906116427405409, 0.3895738260219576, 0.3937433501993539, 0.36858183633802327, 0.33446009159634316, 0.3884317531589484, 0.46741174253482987, 0.27276878051150066, 0.41437676904625514, 0.41752461395158635, 0.37899779987721455, 0.36645818899995364, 0.42218206735391794, 0.4199528332673603, 0.36639903445709926, 0.3656055229202129, 0.4448957885345691, 0.4222783902336476, 0.42861125064883526, 0.40875255589734005, 0.42037840448647307, 0.40784167486554596, 0.43398920031944094, 0.4312729186122849, 0.5232602383766208, 0.3537590324318279, 0.4308698066419294, 0.39521233250606214, 0.43628524862401236, 0.43416682148755276, 0.505902166362936, 0.42811646500508965, 0.37338280645889427, 0.3947756834885681, 0.37322236000409437, 0.4155734597445805, 0.39082251644399596, 0.40310836355944707, 0.395961815698299, 0.36159694026553113, 0.36532594638921256, 0.44712499881230566, 0.4208554876537378, 0.4114800331217359, 0.4338686733356697, 0.4229507413730558, 0.38538448141004994, 0.42881931543037827, 0.4175263817989803, 0.39217791741320907, 0.37660163315333717, 0.400062620334388, 0.35754424680352526, 0.4056026029981082, 0.4209321667290099, 0.3687529127879699, 0.3125710563524516, 0.33678824323839535, 0.2719258857732553, 0.3338110480772194, 0.32966477135052963, 0.3405858034666539, 0.30861276306978497, 0.317720253184521, 0.4525747989761004, 0.39815505628734293, 0.41626242928244794, 0.40992508482261997, 0.40766776112702013, 0.43606672053666873, 0.4067910024681659, 0.37631792372467765, 0.0992980550988829, 0.1139481265159695, 0.0869197349324357, 0.16785741683355368, 0.11573238390738243, 0.07871307828956393, 0.12684164990258412, 0.0856959486230288, 0.40767810332431037, 0.3928237124646254, 0.3528535021441879, 0.39181972602287896, 0.4001778501042579, 0.3827569260765583, 0.3911005729186368, 0.4144097236604698, 0.46258514531579936, 0.4459577009618693, 0.40228363457786787, 0.3956984985246744, 0.4499004792074212, 0.415825801438534, 0.44442844365190226, 0.4327409238742284, 0.48335183580498775, 0.4723646156584728, 0.5138396551901641, 0.502954163151842, 0.46852032140007677, 0.4922786613802512, 0.514951294471292, 0.45335194216578906, 0.39601917239414547, 0.4198749098489404, 0.45754566535154634, 0.4672451346091814, 0.41709926026621946, 0.4746096879821277, 0.3946809567633838, 0.4333913749765745, 0.4546763606889827, 0.46744409927173086, 0.45255817505824747, 0.49712151757976636, 0.47030647061901676, 0.4633823863841151, 0.4428747163779644, 0.47049145156514965, 0.4511750044794822, 0.414157569311347, 0.41595183556824417, 0.4141599624378249, 0.39711150045615307, 0.4345892359688866, 0.4498955436300706, 0.42824207501660755, 0.3726885502659128, 0.35225022887673674, 0.4172810770270656, 0.3959925881186866, 0.36421232786459773, 0.41424664336409567, 0.37590248609429644, 0.3870082358694778, 0.32907408140309324, 0.36020515929015234, 0.3640522685344629, 0.3360098666091143, 0.32237406882981834, 0.30866331029805877, 0.3121758865823208, 0.3597574078365001, 0.5631304735149948, 0.41172691776002196, 0.3994565503365075, 0.43301719061078414, 0.4560264985828077, 0.3966641598681113, 0.5632570738264885, 0.41593650420206035]\n",
"85\n",
"0.07871307828956393 0.5632570738264885\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"r=0\n",
"for idx,image_name in enumerate(image_names):\n",
"    \n",
"    if r==err_ind:\n",
"      print(image_name)\n",
"      similar_image = image_name\n",
"      name = image_name[18:20]\n",
"      if name[-1] == '/':\n",
"       name = name[0]\n",
"      # print(int(name))\n",
"    r=r+1 "
],
"id": "n12pGgN7W9tT",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "20543eaa-2bb8-419f-a12c-12905056b6e6"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"/content/train_small/s2/7.pgm\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"img_similar = cv2.resize(img_sim, (92,112)).flatten()"
],
"id": "yaFcbz1phGgK"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"fig,axarr = plt.subplots()\n",
"axarr.set_title(\" plot_most_similar_vector\")\n",
"avg_image = np.reshape(img_similar, (imgShape))\n",
"axarr.imshow(avg_image, cmap=plt.cm.gray)"
],
"colab": {
"base_uri": "https://localhost:8080/",
"height": 298
},
"id": "JEqxjd_vhzLB",
"outputId": "8663d75c-9830-44b3-ffd2-77b3171baee2"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f3181e59f90>"
]
},
"execution_count": 34
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
},
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"source": [
"Accuracy calculation on the test dataset.\n"
],
"id": "9VPEK34E1fA2"
}
},
{
"cell_type": "code",
"source": [
"IMAGE_DIR_TEST = '/content/test1'\n",
"image_names_test = []\n",
"image_dictionary_test = []\n",
"\n",
"image_1D_test = []\n",
"for root, dirnames, filenames in os.walk(IMAGE_DIR_TEST):\n",
"    for filename in fnmatch.filter(filenames, \"*.*\"):\n",
"        image_names_test.append(os.path.join(root, filename))\n",
"for idx,image_name in enumerate(image_names_test):\n",
"    if idx == 0:\n",
"        imgShape = img.shape\n",
"    image_dictionary_test.append((image_name,img,getClassFromName(image_name)))\n",
"    image_1D_test.append(img.flatten())\n",
"a_transpose_norm_test = []\n",
"\n",
"for i in range(len(image_1D_test)):\n",
"  a_transpose_norm_test.append([])\n",
"  for j in range(len(mean)):\n",
"    a_transpose_norm_test[i].append(image_1D_test[i][j] - mean[j])\n",
"w_array_test=[]\n",
"for i in range(len(image_1D_test)):\n",
"  w=np.linalg.lstsq(np.transpose(u_k),np.transpose(a_transpose_norm_test[i]))\n",
"  w_array_test.append(w[0])\n",
"print(len(w_array_test), len(w_array_test[0]))\n",
"err_ind_test=[]\n",
"errors=[]\n",
"for i in range(len(image_1D_test)):\n",
"  err_list_test=[]\n",
"  for j in range(len(image_1D)):\n",
"    err_list_test.append(np.linalg.norm(w_array[j]-w_array_test[i]))\n",
"  for k in range(len(err_list_test)):\n",
"    if err_list_test[k]==min(err_list_test):\n",
"      err_ind_test.append(k)\n",
"  errors.append(min(err_list_test))\n",
"  # print(min(err_list_test))\n",
"print(err_ind_test)\n",
"print(errors)\n",
"print(min(errors), max(errors))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "4ujYnKaKNhOP",
"outputId": "7887a311-328f-4914-865e-aecc9da1bca4"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"40 12\n",
"[93, 30, 18, 99, 83, 132, 69, 10, 55, 36, 37, 110, 123, 99, 153, 85, 44, 3, 44, 99, 154, 123, 74, 146, 7, 21, 56, 8, 88, 136, 65, 24, 112, 136, 55, 110, 5, 76, 57, 127]\n",
"[0.0757127465319844, 0.10885643270758318, 0.09982672432289147, 0.22965267358321398, 0.09663999294457895, 0.10747999023965292, 0.055989675997151954, 0.16283310445990043, 0.14024121457987115, 0.08898125784699758, 0.1091917765266306, 0.0421484701167536, 0.13195768691294044, 0.10475370669325086, 0.10345169369490421, 0.07871307828956393, 0.12175428724950767, 0.11715511620447168, 0.11937662312615109, 0.11984501287376065, 0.1837596768150345, 0.20196556808851845, 0.0657074177531883, 0.06459352913082324, 0.11651594954608181, 0.0658201048666385, 0.10880310269229757, 0.16724841426724457, 0.09996120926750159, 0.03269611984829349, 0.05048778170214982, 0.08773380517183153, 0.18297053305111705, 0.12392150772000826, 0.12214481272783141, 0.0843174151116105, 0.09381321355844549, 0.06815983554787529, 0.08350351134064858, 0.11261886054143717]\n",
"0.03269611984829349 0.22965267358321398\n"
]
},
{
"output_type": "stream",
"name": "stderr",
"text": [
"/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:23: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.\n",
"To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"IMAGE_DIR_TEST = '/content/test2'"
],
"id": "MB2bRSHA4kAR"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"image_names_test = []\n",
"image_dictionary_test = []\n",
"\n",
"image_1D_test = []\n",
"for root, dirnames, filenames in os.walk(IMAGE_DIR_TEST):\n",
"    for filename in fnmatch.filter(filenames, \"*.*\"):\n",
"        image_names_test.append(os.path.join(root, filename))\n",
"for idx,image_name in enumerate(image_names_test):\n",
"    if idx == 0:\n",
"        # the shape of the image. They are sopposed to be the same\n",
"        imgShape = img.shape\n",
"        # the normalized image matrix. it will be normalized by subtracting from the average image later\n",
"    #img = cv2.pyrDown(img)\n",
"    image_dictionary_test.append((image_name,img,getClassFromName(image_name)))\n",
"    image_1D_test.append(img.flatten())\n",
"\n",
"# print(image_dictionary_test)"
],
"id": "BFLudewz1h8-"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# print(image_1D)  # 92x112\n",
"print(len(image_1D_test))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "B-or36Qx4quc",
"outputId": "f662794d-535a-46c8-b3da-d48da144191c"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"40\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"a_transpose_norm_test = []\n",
"\n",
"for i in range(len(image_1D_test)):\n",
"  a_transpose_norm_test.append([])\n",
"  for j in range(len(mean)):\n",
"    a_transpose_norm_test[i].append(image_1D_test[i][j] - mean[j])\n",
"    # print(a_transpose_norm)\n",
"\n",
"# print(len(a_transpose_norm))"
],
"id": "-ifHHsLd7CQ8"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"#storing the weights of each training image in an array.\n",
"w_array_test=[]\n",
"for i in range(len(image_1D_test)):\n",
"  w=np.linalg.lstsq(np.transpose(u_k),np.transpose(a_transpose_norm_test[i]))\n",
"  w_array_test.append(w[0])\n",
"print(len(w_array_test), len(w_array_test[0]))\n",
"# w_array_test"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "-gHiREMt4-mk",
"outputId": "6752a94f-3313-4454-9782-76c5f3263b47"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"40 12\n"
]
},
{
"output_type": "stream",
"name": "stderr",
"text": [
"/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:4: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.\n",
"To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.\n",
"  after removing the cwd from sys.path.\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"err_ind_test2=[]\n",
"errors2=[]\n",
"for i in range(len(image_1D_test)):\n",
"  err_list_test=[]\n",
"  for j in range(len(image_1D)):\n",
"    err_list_test.append(np.linalg.norm(w_array[j]-w_array_test[i]))\n",
"  for k in range(len(err_list_test)):\n",
"    if err_list_test[k]==min(err_list_test):\n",
"      err_ind_test2.append(k)\n",
"  errors2.append(min(err_list_test))\n",
"  # print(min(err_list_test))\n",
"print(err_ind_test2)\n",
"print(errors2)\n",
"print(min(errors2), max(errors2))"
],
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "-O5R9H1sKl6t",
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[70, 80, 64, 64, 142, 139, 98, 67, 74, 70, 136, 24, 94, 53, 23, 78, 3, 65, 74, 64, 18, 29, 26, 64, 148, 136, 43, 29, 64, 19, 64, 26, 69, 145, 157, 67, 98, 65, 66, 25]\n",
"[0.24455933614674108, 0.21225727440574949, 0.21483738113923947, 0.2264812212568616, 0.19503708762652225, 0.21052439930504327, 0.21937298516722972, 0.20007678390656794, 0.18103627681490483, 0.25375188437646584, 0.1898239623952792, 0.2095789084573638, 0.16793299966164493, 0.15377921146663465, 0.21237820988615969, 0.15129736285049772, 0.19429071916624643, 0.22181699853680736, 0.2172953972464706, 0.1851673660516963, 0.18568749015993063, 0.16346036514447684, 0.17130978526360258, 0.25363554542627026, 0.14079092639207766, 0.18591898763766568, 0.20677666448000173, 0.17019033105945425, 0.24572292568018825, 0.22270775040965246, 0.20489410866428956, 0.20714207572106164, 0.14314830244653792, 0.15424412868661652, 0.21356987051130216, 0.17955444373324905, 0.21084554196768995, 0.18143765852048863, 0.21813505783692944, 0.15510790948049472]\n",
"0.14079092639207766 0.25375188437646584\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"tp=0  # true positive\n",
"tn=0  # true negative\n",
"fp=0  # false poaitive\n",
"fn=0  # false negative\n",
"threshold = (min(errors) + max(errors))/2\n",
"\n",
"for i in range(len(errors)):\n",
"  if errors[i] > threshold :\n",
"    fn+=1\n",
"  elif errors[i] <= threshold:\n",
"    tp+=1 \n",
"\n",
"for i in range(len(errors2)):\n",
"  if errors2[i] > threshold :\n",
"    tn+=1\n",
"  elif errors2[i] <= threshold:\n",
"    fp+=1 \n",
"\n",
"incorrect_classifications = fp+fn\n",
"print(incorrect_classifications)"
],
"id": "JW03DY0OAT63",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "efc9514d-31b3-4f51-91d3-b7157087d18f"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"8\n"
]
}
]
}
]
}```

Used the approach mentioned in the research paper by Matthew Turk and Alex Pentland, for face recognition using Eigenfaces. The algorithm was implemented using basic matrix algebra and numpy.
Link to the research paper: https://ieeexplore.ieee.org/document/139758

``!pip install opencv-python``
```Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Requirement already satisfied: opencv-python in /usr/local/lib/python3.7/dist-packages (4.6.0.66)
Requirement already satisfied: numpy&amp;gt;=1.14.5 in /usr/local/lib/python3.7/dist-packages (from opencv-python) (1.21.6)
```
``````# taken from this StackOverflow answer: https://stackoverflow.com/a/39225039
import requests

session = requests.Session()

response = session.get(URL, params = { 'id' : id }, stream = True)
token = get_confirm_token(response)

if token:
params = { 'id' : id, 'confirm' : token }
response = session.get(URL, params = params, stream = True)

save_response_content(response, destination)

def get_confirm_token(response):
return value

return None

def save_response_content(response, destination):
CHUNK_SIZE = 32768

with open(destination, "wb") as f:
for chunk in response.iter_content(CHUNK_SIZE):
if chunk: # filter out keep-alive new chunks
f.write(chunk)``````

The dataset used was the AT&T dataset, where 10 different images of 40 distinct subjects were given. The 10 images of the same person were taken under varying circumstances, like different lighting, facial expressions and facial accessories.

We took two images of each of the 40 people for testing. The model was trained on 8 images of the first 20 people. We did this so that we can calculate the accuracy for people both inside and outside our training set.

On running the code, train_small.zip, test1.zip and test2.zip will appear in the contents folder. These signify the following:

1. train_small: training dataset, contains 8 images of 20 different people.
2. test1.zip: testing dataset, contains 2 images all people from the training dataset.
3. test2.zip: testing dataset, consisting of 2 images of 20 new people whose images weren't present in the training dataset.
``````# Downloading training dataset
file_id = '1Z9evWwUK4nTpARz67ZWraNe5sX2MNcFx'
destination = '/content/dataset.zip'

!unzip -q dataset.zip
!rm -rf dataset.zip``````
``````# Downloading test1 dataset
test_file_id_1 = '1bIr_ikTxGuuZnJulykXeZz04pyb27S3f'
test_destination_1 = '/content/test1.zip'

!unzip -q test1.zip
!rm -rf test1.zip``````
``````# Downloading test2 dataset
test_file_id_2 = '1Kj0QsxJ1m0n0UCPiaFskskUhM7fvxqS4'
test_destination_2 = '/content/test2.zip'

!unzip -q test2.zip
!rm -rf test2.zip``````
``````# All images are supposed to be the same size, say, N*L
IMAGE_DIR = "/content/train_small"``````
``````# importing necessary libraries

import os
import numpy as np
import cv2
import matplotlib.pyplot as plt
import fnmatch
import re``````
``````def getClassFromName(fileName,lastSubdir=True):
if lastSubdir:
name = os.path.basename(os.path.dirname(fileName))
else:
name = os.path.basename(fileName)
mat = re.match(".*(\d+).*", name)
if mat != None:
return int(mat.group(1))
else:
return name.__hash__()``````
``````image_names = []
image_dictionary = []

image_1D = []
for root, dirnames, filenames in os.walk(IMAGE_DIR):
for filename in fnmatch.filter(filenames, "*.*"):
image_names.append(os.path.join(root, filename))
for idx,image_name in enumerate(image_names):
if idx == 0:
imgShape = img.shape
vector_matrix = np.zeros((imgShape[0]*imgShape[1], len(image_names)),dtype=np.float64)
image_dictionary.append((image_name,img,getClassFromName(image_name)))
image_1D.append(img.flatten())``````
``````# print(image_1D)
print(len(image_1D))``````
```160
```

Training Methodology:

1. We start by grayscaling the images and converting them into matrices of shape 112x92.
2. Now each of these matrices was flattened and converted into a matrix of shape 10304x1. (Here 10304 comes from 112*92). All these vectors were stacked row wise into a single matrix (image_1D in our code).
3. Now we normalize each row of this matrix by subtracting the row wise mean from each element of the corresponding row. This new matrix will be called AT, and the transpose of this matrix will be called A.
4. Next we calculate the covariance matrix by doing ATxA.
5. Next we calculate the eigenvalues and eigenvectors of the covariance matrix using the linalg.eig of numpy.
6. Next step is dimensionality reduction. We choose a number K, and choose K eigen vectors corresponding to the K largest eigenvalues.
7. Now we calculated the normalized training faces (face-average face) and represented each normalized face as a linear combination of the eigenvectors obtained in step 6. These w vectors were calculated using the np.linalg.lstsq function of numpy.
8. After calculating the weights (w vectors), we stacked those vectors

Calculating the normalized image vectors.

``````# We normalize each row of this matrix by subtracting the row wise mean from each element of the corresponding row.
# This new matrix will be called AT
mean = []
a_transpose_norm = []
for i in range(len(image_1D[0])):
mean.append(0)

for j in range(len(image_1D)):
mean[i] += image_1D[j][i]/len(image_1D)
# print(sum)

for i in range(len(image_1D)):
a_transpose_norm.append([])
for j in range(len(mean)):
a_transpose_norm[i].append(image_1D[i][j] - mean[j])
# print(a_transpose_norm)

# print(len(a_transpose_norm))``````
``````# The transpose of the matrix computed above will be called A.
a_norm = np.transpose(a_transpose_norm)  #A
len(a_norm)``````
`10304`

Calculating eigenvectors and eigenvalues of the covariance matrix formed by the image vectors.

``````# We calculate the covariance matrix by doing ATxA.
cov_matrix = np.cov(a_transpose_norm) # At*A
# print(cov_matrix)
len(cov_matrix[0])``````
`160`
``````eigen = np.linalg.eig(cov_matrix) # returns eigen values and then all eigen vectors
# for i in range(len(eigen)):
#   print(eigen[i])
v_eigenvalues=eigen[0]
v=np.transpose(eigen[1])
# print(v_eigenvalues)
# print(v)
# print(len(v), len(v[0]))
``````
``````u_transpose = []
for i in range(len(v)):
array = np.matmul(a_norm,v[i])
u_transpose.append(array)
u=np.transpose(u_transpose)
# print(len(u),len(u[0]))
print(len(u), len(u[0]))``````
```10304 160
```
``````eigen_values = eigen[0]
eigen_vectors=eigen[1]
# print(eigen_values)
eigen_d = {}
for i in range(len(eigen_values)):
eigen_d[eigen_values[i]]=i
# eigen_d``````

Selecting the K eigenvectors of covariance matrix corresponding to the K largest eigenvalues.

``k=12``
``````# sorting the dictionary of eigenvalues to get the corresponding eigenvectors.
from collections import OrderedDict
dict1 = OrderedDict(sorted(eigen_d.items(),reverse=True))
dict2=dict(dict1)
print(dict2)``````
```{43219.953977553596: 0, 18749.895990890815: 1, 17942.155464146246: 2, 12061.802455045403: 3, 10489.25912953686: 4, 8066.724722559026: 5, 7297.85172164008: 6, 6261.016588366359: 7, 5873.753178029104: 8, 4420.5004066534: 9, 3826.304473465676: 10, 3579.8886501814827: 11, 3112.701941552233: 12, 2932.3449009364517: 13, 2747.3196034473535: 14, 2487.396345846331: 15, 2411.0446487988524: 16, 2252.6641238208167: 17, 2074.7096367875374: 18, 1989.9475765463246: 19, 1928.8795510110008: 20, 1773.305425328178: 21, 1676.8247434736688: 22, 1640.8845693566923: 23, 1586.0134088610828: 24, 1384.3119343572707: 25, 1360.5249845839646: 26, 1272.8354997100732: 27, 1171.4911399813118: 28, 1150.5295704016391: 29, 1117.2277311946657: 30, 1066.7345849297926: 31, 1027.8242127649535: 32, 1000.5604997800493: 33, 957.4881339639342: 34, 932.1908536264845: 35, 890.6505933876211: 36, 867.9216091629972: 38, 833.6071838643115: 39, 806.8325487486294: 40, 774.5620675914377: 41, 758.6272156532845: 42, 738.4342113595159: 43, 714.5399164439951: 44, 682.7055539009281: 46, 680.9252271100078: 47, 673.9283018815898: 48, 658.4301569913085: 45, 625.0816864277112: 49, 617.5582835272636: 50, 606.4179117332367: 51, 574.3310372756353: 53, 569.9325407493129: 52, 556.968211979823: 54, 548.371195855361: 55, 541.394394333996: 56, 517.6264019518915: 58, 516.5821198500923: 57, 500.04350432768587: 59, 482.81038227024146: 60, 474.40612112126905: 61, 472.91907873668464: 62, 463.37362069900644: 63, 448.87411947393264: 64, 445.1195525159666: 65, 433.8822394567646: 66, 424.9545193027636: 67, 414.34625398368985: 73, 410.44103052260715: 72, 399.7720057166255: 74, 392.1543734446897: 75, 387.79362525258114: 76, 374.2368664887361: 79, 371.49945348490684: 80, 366.1104550707202: 81, 362.76582599959437: 83, 362.07916777129213: 82, 352.7149467318006: 86, 347.6629266571733: 87, 344.4517149718263: 88, 338.56891140470464: 89, 326.7105220744234: 94, 326.25054239097585: 95, 317.973905297458: 99, 315.61948544607054: 100, 312.15439105645754: 109, 308.5046455356127: 101, 302.55416730618424: 110, 298.5400400481408: 111, 292.27487160513783: 112, 288.8823139316889: 113, 285.0435271976845: 114, 282.9772519873982: 115, 277.64467614646475: 117, 273.7020381676069: 118, 269.5357634357952: 142, 265.9471151508216: 119, 261.3862164259361: 120, 259.8671420930868: 126, 257.6130828977115: 125, 254.21906797290566: 131, 250.616479699577: 128, 246.06438730855305: 127, 240.00699924404051: 129, 234.8180913874552: 130, 232.7549425732958: 141, 230.7956380602637: 143, 226.5311551599993: 159, 223.75397178988626: 153, 221.54950660799236: 152, 219.43463583127505: 158, 217.41411147378702: 151, 215.48480958242658: 150, 211.49682062225486: 154, 209.55479232153124: 157, 208.1694532219256: 156, 206.43451832745535: 155, 200.65013822053376: 144, 199.90465610231152: 145, 197.0978066449791: 140, 195.18560080202585: 147, 190.91520321768897: 146, 189.6685050111701: 137, 185.6900961024561: 139, 182.2508248568398: 136, 178.73701239142918: 135, 174.5908773381799: 132, 169.827660924428: 124, 166.7766873707503: 134, 165.7343487334624: 138, 163.50086445520705: 133, 161.8161444605663: 149, 159.93509949384642: 123, 157.84439541824133: 121, 155.2947155213594: 148, 154.80023084350475: 122, 150.43467043710345: 116, 147.1590447262029: 108, 140.48035960506212: 107, 138.73007592494284: 106, 137.8886194586964: 105, 133.96609468111802: 104, 133.32671443969662: 103, 131.35871093197667: 102, 126.39832659543461: 98, 123.8572162371065: 97, 120.39979904790052: 96, 119.33111585528107: 93, 117.61534130912757: 92, 115.93856715938144: 91, 109.54104484025125: 90, 108.20582883113228: 85, 101.43665329843098: 84, 89.47901931450252: 78, 84.06012945411771: 77, 70.50578026422139: 71, 65.59787544247587: 70, 62.77453678940503: 69, 59.32778617838623: 68, -5.107739735450283e-13: 37}
```
``````# indexes of of k maximum eigenvalues
index_list=[]
for e in dict2:
if(len(index_list)&gt;=k):
break
index_list.append(dict2[e])
print(index_list)``````
```[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
```
``````# eigenvectors of k maximum eigenvalues
u_k=[]
for i in index_list:
u_k.append(u_transpose[i])
print(u_k)``````
```[array([-250.34987268, -246.96739775, -251.03150872, ...,   62.66394197,
42.95102603,   -7.43283506]), array([-293.03400587, -296.61765524, -294.39034777, ...,  -50.55568765,
-45.94985846,  -50.66399445]), array([ 69.73691919,  64.22732671,  68.583571  , ..., -41.61421501,
-40.95085605, -38.69027747]), array([ 15.24047245,  19.31637724,  22.9986019 , ..., -81.3522821 ,
-68.21885398, -73.1093675 ]), array([   7.04373461,    4.56640216,    2.24472334, ..., -102.02376868,
-80.93066914,  -59.14922928]), array([-64.63035609, -68.56599373, -60.92922784, ...,  97.30812891,
83.50398642,  56.29972771]), array([-73.39842816, -75.85858873, -75.10925541, ..., -21.30720511,
-25.49241544,   5.10502217]), array([  76.33460672,   78.27079323,   83.86525799, ..., -100.27234286,
-77.988847  ,  -61.0207666 ]), array([-103.25654954, -100.23979122,  -96.30983044, ...,  -37.3388256 ,
-49.91948021,  -28.46092446]), array([-62.26684061, -59.45034204, -62.54270953, ..., 151.8902004 ,
121.29818377, 111.59794073]), array([ -92.97767444,  -95.5290902 ,  -91.18621931, ..., -113.1381992 ,
-91.31555489,  -88.30228713]), array([-74.61218527, -70.83391408, -71.92315934, ...,  52.7331185 ,
48.02889301,  55.92254778])]
```

Plotting the mean vector.

``````fig,axarr = plt.subplots()
axarr.set_title(" plot_mean_vector")
avg_image = np.reshape(mean, (imgShape))
axarr.imshow(avg_image, cmap=plt.cm.gray)``````
`&lt;matplotlib.image.AxesImage at 0x7f3182920b10&gt;`

Plotting the k eigenfaces.

``````for i in range(k):
fig,axarr = plt.subplots()
axarr.set_title(" plot_eigen_face_"+str(i+1))
avg_image = np.reshape(u_k[i], (imgShape))
axarr.imshow(avg_image, cmap=plt.cm.gray)``````