{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:06:15.533290Z",
     "start_time": "2018-07-21T07:06:15.509560Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The autoreload extension is already loaded. To reload it, use:\n",
      "  %reload_ext autoreload\n"
     ]
    }
   ],
   "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\n",
    "import mxnet as mx\n",
    "import io\n",
    "from pathlib import Path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:08:15.237357Z",
     "start_time": "2018-07-21T07:08:15.214563Z"
    }
   },
   "outputs": [],
   "source": [
    "face_folder = Path('/home/f/learning/Dataset/faces_vgg_112x112')\n",
    "bin_path = face_folder/'train.rec'\n",
    "idx_path = face_folder/'train.idx'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:08:20.176501Z",
     "start_time": "2018-07-21T07:08:17.337626Z"
    }
   },
   "outputs": [],
   "source": [
    "imgrec = mx.recordio.MXIndexedRecordIO(str(idx_path), str(bin_path), 'r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:10:25.708722Z",
     "start_time": "2018-07-21T07:10:25.687476Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "HEADER(flag=0, label=2.0, id=813, id2=0)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 27672 characters]\n",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=112x112 at 0x7FCAB5C7C048>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "i =813\n",
    "\n",
    "img_info = imgrec.read_idx(i)\n",
    "\n",
    "header, img = mx.recordio.unpack(img_info)\n",
    "\n",
    "encoded_jpg_io = io.BytesIO(img)\n",
    "\n",
    "image = Image.open(encoded_jpg_io)\n",
    "\n",
    "print(header)\n",
    "image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:10:26.732578Z",
     "start_time": "2018-07-21T07:10:26.711066Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(112, 112)"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image.size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:10:29.714824Z",
     "start_time": "2018-07-21T07:10:29.676756Z"
    }
   },
   "outputs": [],
   "source": [
    "bounding_boxes, landmarks = detect_faces(image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:10:30.404858Z",
     "start_time": "2018-07-21T07:10:30.386340Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 13.36201936,   5.58984986,  78.93511893, 104.44713098,\n",
       "           0.99996698]]),\n",
       " array([[45.040733, 73.22949 , 67.01588 , 46.294598, 68.35203 , 47.975132,\n",
       "         46.75182 , 68.91486 , 85.37722 , 84.38674 ]], dtype=float32))"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bounding_boxes,landmarks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:14:20.172835Z",
     "start_time": "2018-07-21T07:14:20.138160Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  0%|          | 0/1 [00:00<?, ?it/s]\n"
     ]
    },
    {
     "ename": "FaceWarpException",
     "evalue": "In File /root/Notebooks/face/mtcnn-pytorch/src/align_trans.py:FaceWarpException('No paddings to do, output_size must be None or [ 96 112]',)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mFaceWarpException\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-36-1da710ed1190>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     14\u001b[0m     \u001b[0mlandmark\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlandmarks\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     15\u001b[0m     \u001b[0mfacial5points\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mlandmark\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mbox\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mlandmark\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mbox\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 16\u001b[0;31m     \u001b[0mdst_img\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwarp_and_crop_face\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mface\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mfacial5points\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcrop_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m112\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m112\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     17\u001b[0m     \u001b[0mfaces\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mImage\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdst_img\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m...\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/Notebooks/face/mtcnn-pytorch/src/align_trans.py\u001b[0m in \u001b[0;36mwarp_and_crop_face\u001b[0;34m(src_img, facial_pts, reference_pts, crop_size, align_type)\u001b[0m\n\u001b[1;32m    258\u001b[0m                                                         \u001b[0minner_padding_factor\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    259\u001b[0m                                                         \u001b[0mouter_padding\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 260\u001b[0;31m                                                         default_square)\n\u001b[0m\u001b[1;32m    261\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    262\u001b[0m     \u001b[0mref_pts\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfloat32\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreference_pts\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/Notebooks/face/mtcnn-pytorch/src/align_trans.py\u001b[0m in \u001b[0;36mget_reference_facial_points\u001b[0;34m(output_size, inner_padding_factor, outer_padding, default_square)\u001b[0m\n\u001b[1;32m    102\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    103\u001b[0m             raise FaceWarpException(\n\u001b[0;32m--> 104\u001b[0;31m                 'No paddings to do, output_size must be None or {}'.format(tmp_crop_size))\n\u001b[0m\u001b[1;32m    105\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    106\u001b[0m     \u001b[0;31m# check output size\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mFaceWarpException\u001b[0m: In File /root/Notebooks/face/mtcnn-pytorch/src/align_trans.py:FaceWarpException('No paddings to do, output_size must be None or [ 96 112]',)"
     ]
    }
   ],
   "source": [
    "from tqdm import tqdm\n",
    "faces = []\n",
    "img_cv2 = np.array(image)[...,::-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, crop_size=(112,112))\n",
    "    faces.append(Image.fromarray(dst_img[...,::-1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:21:45.873749Z",
     "start_time": "2018-07-21T07:21:45.857902Z"
    }
   },
   "outputs": [],
   "source": [
    "reference_pts = get_reference_facial_points(default_square= True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:22:21.544120Z",
     "start_time": "2018-07-21T07:22:21.517479Z"
    }
   },
   "outputs": [
    {
     "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": [
    "dst_img = warp_and_crop_face(face, facial5points, reference_pts, crop_size=(112,112))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-07-21T07:22:31.344783Z",
     "start_time": "2018-07-21T07:22:31.313710Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 17492 characters]\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=112x112 at 0x7FCAB5CB4438>"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "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
}
