File size: 3,957 Bytes
4e75693
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2c2df050-8d87-467a-bac4-db82196f9476",
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from math import atan2\n",
    "from os import listdir, path\n",
    "from PIL import Image as PImage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "66f93746-7ea0-4856-ac86-24472166cf8c",
   "metadata": {},
   "outputs": [],
   "source": [
    "img_filename = \"MT.png\"\n",
    "\n",
    "pimg = PImage.open(f\"./{img_filename}\").convert(\"L\")\n",
    "pimg.thumbnail((1000,1000))\n",
    "imgg = np.array(pimg).copy()\n",
    "\n",
    "iw,ih = pimg.size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "86c17ae6-391b-474f-a157-71af179f29a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://medium.com/analytics-vidhya/facial-landmarks-and-face-detection-in-python-with-opencv-73979391f30e\n",
    "# https://www.researchgate.net/figure/The-68-specific-human-face-landmarks_fig4_331769278\n",
    "\n",
    "haarcascade = \"./models/haarcascade_frontalface_alt2.xml\"\n",
    "face_detector = cv2.CascadeClassifier(haarcascade)\n",
    "\n",
    "LBFmodel = \"./models/lbfmodel.yaml\"\n",
    "landmark_detector  = cv2.face.createFacemarkLBF()\n",
    "landmark_detector.loadModel(LBFmodel)\n",
    "\n",
    "faces = face_detector.detectMultiScale(imgg)\n",
    "\n",
    "biggest_faces = faces[np.argsort(-faces[:,2])]\n",
    "\n",
    "_, landmarks = landmark_detector.fit(imgg, biggest_faces)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7724f3dd-ee63-48a3-8761-a0ae065c480f",
   "metadata": {},
   "outputs": [],
   "source": [
    "OUT_W = 130\n",
    "OUT_H = 170\n",
    "OUT_EYE_SPACE = 60\n",
    "OUT_NOSE_TOP = 70\n",
    "\n",
    "EYE_0_IDX = 36\n",
    "EYE_1_IDX = 45\n",
    "CHIN_IDX = 8\n",
    "\n",
    "for landmark in landmarks:\n",
    "  eye0 = np.array(landmark[0][EYE_0_IDX])\n",
    "  eye1 = np.array(landmark[0][EYE_1_IDX])\n",
    "  chin = np.array(landmark[0][CHIN_IDX])\n",
    "  mid = np.mean([eye0, eye1], axis=0)\n",
    "\n",
    "  eye_line = eye1 - eye0\n",
    "  tilt = atan2(eye_line[1], eye_line[0])\n",
    "  tilt_deg = 180 * tilt / np.pi\n",
    "  print(tilt_deg)\n",
    "\n",
    "  chin_line = chin - mid\n",
    "  tilt2 = atan2(chin_line[1], chin_line[0])\n",
    "  tilt2_deg = (180 * tilt2 / np.pi) - 90\n",
    "  print(tilt2_deg)\n",
    "\n",
    "  scale = OUT_EYE_SPACE / abs(eye0[0] - eye1[0])\n",
    "\n",
    "  # scale\n",
    "  pimgs = pimg.resize((int(iw * scale), int(ih * scale)), resample=PImage.Resampling.LANCZOS)\n",
    "\n",
    "  # rotate around nose\n",
    "  new_mid = [int(c * scale) for c in mid]\n",
    "  crop_box = (new_mid[0] - (OUT_W // 2),\n",
    "              new_mid[1] - OUT_NOSE_TOP,\n",
    "              new_mid[0] + (OUT_W // 2),\n",
    "              new_mid[1] + (OUT_H - OUT_NOSE_TOP))\n",
    "\n",
    "  pimgsrc0 = pimgs.rotate(0, center=new_mid, resample=PImage.Resampling.BICUBIC).crop(crop_box)\n",
    "  display(pimgsrc0)\n",
    "  pimgsrc = pimgs.rotate(tilt_deg, center=new_mid, resample=PImage.Resampling.BICUBIC).crop(crop_box)\n",
    "  display(pimgsrc)\n",
    "  pimgsrc2 = pimgs.rotate(tilt_deg, center=new_mid, resample=PImage.Resampling.BICUBIC).crop(crop_box)\n",
    "  display(pimgsrc2)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}