{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T15:57:52.964962Z",
     "start_time": "2018-07-17T15:57:52.733030Z"
    }
   },
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "from src import detect_faces, show_bboxes\n",
    "from PIL import Image\n",
    "import cv2\n",
    "import numpy as np\n",
    "from src.align_trans import get_reference_facial_points, warp_and_crop_face"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:19:04.738385Z",
     "start_time": "2018-07-17T16:19:04.722491Z"
    }
   },
   "outputs": [],
   "source": [
    "img = Image.open('images/jf.jpg')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:19:05.404315Z",
     "start_time": "2018-07-17T16:19:05.386648Z"
    }
   },
   "outputs": [],
   "source": [
    "img_cv2 = np.array(img)[...,::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:19:06.526587Z",
     "start_time": "2018-07-17T16:19:06.471323Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 393940 characters]\n",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=487x620 at 0x7F0D2A5B6EF0>"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:09.169671Z",
     "start_time": "2018-07-17T16:23:09.153554Z"
    }
   },
   "outputs": [],
   "source": [
    "src = np.array([                                                                                                                                                                     \n",
    " [30.2946, 51.6963],                                                                                                                                                                \n",
    " [65.5318, 51.5014],                                                                                                                                                                \n",
    " [48.0252, 71.7366],                                                                                                                                                                \n",
    " [33.5493, 92.3655],                                                                                                                                                                \n",
    " [62.7299, 92.2041] ], dtype=np.float32 )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:11.508250Z",
     "start_time": "2018-07-17T16:23:11.492667Z"
    }
   },
   "outputs": [],
   "source": [
    "src[:,0] *= (img.size[0]/96)\n",
    "src[:,1] *= (img.size[1]/112)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:22:17.799054Z",
     "start_time": "2018-07-17T16:22:17.782642Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(487, 620)"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "img.size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:15.770636Z",
     "start_time": "2018-07-17T16:23:15.754943Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[153.68198, 286.17593],\n",
       "       [332.43735, 285.09702],\n",
       "       [243.62782, 397.11334],\n",
       "       [170.19281, 511.30902],\n",
       "       [318.22354, 510.41556]], dtype=float32)"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "src"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:24.517969Z",
     "start_time": "2018-07-17T16:23:24.443709Z"
    }
   },
   "outputs": [],
   "source": [
    "bounding_boxes, landmarks = detect_faces(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:24.918524Z",
     "start_time": "2018-07-17T16:23:24.876078Z"
    }
   },
   "outputs": [],
   "source": [
    "dst = landmarks[0].astype(np.float32)\n",
    "\n",
    "facial5points = [[dst[j],dst[j+5]] for j in range(5)]\n",
    "\n",
    "from skimage import transform as trans\n",
    "tform = trans.SimilarityTransform()    \n",
    "\n",
    "                                                                                                                                              \n",
    "tform.estimate(np.array(facial5points), src)\n",
    "\n",
    "M = tform.params[0:2,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:32.708971Z",
     "start_time": "2018-07-17T16:23:32.693365Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.71888965e+00, -1.55000378e-01, -9.29862384e+01],\n",
       "       [ 1.55000378e-01,  1.71888965e+00, -1.97105569e+02]])"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:33.142171Z",
     "start_time": "2018-07-17T16:23:33.125348Z"
    }
   },
   "outputs": [],
   "source": [
    "warped = cv2.warpAffine(img_cv2,M,(img.size[0],img.size[1]), borderValue = 0.0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:35.087035Z",
     "start_time": "2018-07-17T16:23:35.071028Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(620, 487, 3)"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "warped.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:23:36.080655Z",
     "start_time": "2018-07-17T16:23:35.988477Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 406272 characters]\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=487x620 at 0x7F0D2A945B70>"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image.fromarray(warped[...,::-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:15:21.789079Z",
     "start_time": "2018-07-17T16:15:21.771371Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 43528 characters]\n",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=112x131 at 0x7F0D50B74FD0>"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T16:21:53.234255Z",
     "start_time": "2018-07-17T16:21:53.218706Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(96, 112)"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "faces[0].size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-17T15:57:53.095528Z",
     "start_time": "2018-07-17T15:57:52.980025Z"
    }
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a45bffaeb6e04311924cade22ec384c0",
       "version_major": 2,
       "version_minor": 0
      },
      "text/html": [
       "<p>Failed to display Jupyter Widget of type <code>HBox</code>.</p>\n",
       "<p>\n",
       "  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n",
       "  that the widgets JavaScript is still loading. If this message persists, it\n",
       "  likely means that the widgets JavaScript library is either not installed or\n",
       "  not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
       "  Widgets Documentation</a> for setup instructions.\n",
       "</p>\n",
       "<p>\n",
       "  If you're reading this message in another frontend (for example, a static\n",
       "  rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
       "  it may mean that your frontend doesn't currently support widgets.\n",
       "</p>\n"
      ],
      "text/plain": [
       "HBox(children=(IntProgress(value=0, max=8), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/root/Notebooks/face/mtcnn-pytorch/src/matlab_cp2tform.py:90: 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",
      "  r, _, _, _ = lstsq(X, U)\n"
     ]
    }
   ],
   "source": [
    "from tqdm import tqdm_notebook as tqdm\n",
    "bounding_boxes, landmarks = detect_faces(img)\n",
    "faces = []\n",
    "img_cv2 = np.array(img)[...,::-1]\n",
    "for i in tqdm(range(len(bounding_boxes))):\n",
    "    box = bounding_boxes[i][:4].astype(np.int32).tolist()\n",
    "    for idx, coord in enumerate(box[:2]):\n",
    "        if coord > 1:\n",
    "            box[idx] -= 1\n",
    "    if box[2] + 1 < img_cv2.shape[1]:\n",
    "        box[2] += 1\n",
    "    if box[3] + 1 < img_cv2.shape[0]:\n",
    "        box[3] += 1\n",
    "    face = img_cv2[box[1]:box[3],box[0]:box[2]]\n",
    "    landmark = landmarks[i]\n",
    "    facial5points = [[landmark[j] - box[0],landmark[j+5] - box[1]] for j in range(5)]\n",
    "    dst_img = warp_and_crop_face(face,facial5points)\n",
    "    faces.append(Image.fromarray(dst_img[...,::-1]))"
   ]
  }
 ],
 "metadata": {
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
