Skip to content

Commit ed112ee

Browse files
committed
Add Stage3.0
1 parent c2246c2 commit ed112ee

2 files changed

Lines changed: 137 additions & 0 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from os.path import dirname, join
2+
from unittest import TestCase
3+
4+
import numpy as np
5+
6+
import ets_tutorial
7+
from traited_face_detect import ImageFile
8+
9+
TUTORIAL_DIR = dirname(ets_tutorial.__file__)
10+
11+
SAMPLE_IMG_DIR = join(TUTORIAL_DIR, "..", "sample_images")
12+
13+
SAMPLE_IMG1 = join(SAMPLE_IMG_DIR, "IMG-0311_xmas_2020.JPG")
14+
15+
16+
class TestImageFile(TestCase):
17+
def test_no_image_file(self):
18+
img = ImageFile()
19+
self.assertEqual(img.metadata, {})
20+
data = img.to_array()
21+
self.assertIsInstance(data, np.ndarray)
22+
self.assertEqual(data.shape, (0,))
23+
24+
def test_image_metadata(self):
25+
img = ImageFile(filepath=SAMPLE_IMG1)
26+
self.assertNotEqual(img.metadata, {})
27+
for key in ['ExifVersion', 'ExifImageWidth', 'ExifImageHeight']:
28+
self.assertIn(key, img.metadata.keys())
29+
data = img.to_array()
30+
expected_shape = (img.metadata['ExifImageHeight'],
31+
img.metadata['ExifImageWidth'], 3)
32+
self.assertEqual(data.shape, expected_shape)
33+
34+
def test_detects_faces(self):
35+
img = ImageFile(filepath=SAMPLE_IMG1)
36+
self.assertEqual(len(img.faces), 5)
37+
self.assertEqual(img.metadata["Number of faces"], 5)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# General imports
2+
from os.path import join
3+
4+
import PIL.Image
5+
import matplotlib.pyplot as plt
6+
import numpy as np
7+
from matplotlib import patches
8+
from PIL.ExifTags import TAGS
9+
from skimage import data
10+
from skimage.feature import Cascade
11+
12+
# ETS imports
13+
from traits.api import (
14+
Dict,
15+
File,
16+
HasStrictTraits,
17+
List,
18+
observe,
19+
)
20+
from traitsui.api import OKButton, UItem, View
21+
22+
23+
class ImageFile(HasStrictTraits):
24+
""" Model to hold an image file.
25+
"""
26+
filepath = File
27+
28+
faces = List
29+
30+
metadata = Dict
31+
32+
def to_array(self):
33+
if not self.filepath:
34+
return np.array([])
35+
36+
with PIL.Image.open(self.filepath) as img:
37+
return np.asarray(img)
38+
39+
@observe("filepath")
40+
def _update_faces_and_metadata(self, event):
41+
self.metadata = {}
42+
self._update_metadata_with_exif()
43+
self._detect_faces()
44+
print(self.metadata)
45+
print(f"Number of faces: {self.metadata['Number of faces']}")
46+
47+
def _update_metadata_with_exif(self):
48+
if not self.filepath:
49+
return
50+
with PIL.Image.open(self.filepath) as img:
51+
exif = img._getexif()
52+
if not exif:
53+
return
54+
self.metadata.update(
55+
{TAGS[k]: v for k, v in exif.items() if k in TAGS}
56+
)
57+
58+
def _detect_faces(self):
59+
self.faces = []
60+
if not self.filepath:
61+
return
62+
# Load the trained file from the module root.
63+
trained_file = data.lbp_frontal_face_cascade_filename()
64+
# Initialize the detector cascade.
65+
detector = Cascade(trained_file)
66+
faces = detector.detect_multi_scale(
67+
img=self.to_array(),
68+
scale_factor=1.2,
69+
step_ratio=1,
70+
min_size=(60, 60),
71+
max_size=(600, 600)
72+
)
73+
self.faces.extend(faces)
74+
self.metadata['Number of faces'] = len(self.faces)
75+
76+
77+
if __name__ == '__main__':
78+
img = ImageFile()
79+
view = View(
80+
UItem(name='filepath'),
81+
buttons=[OKButton],
82+
resizable=True,
83+
width=640
84+
)
85+
img.configure_traits(view=view)
86+
87+
plt.imshow(img.to_array())
88+
img_desc = plt.gca()
89+
for patch in img.faces:
90+
img_desc.add_patch(
91+
patches.Rectangle(
92+
(patch['c'], patch['r']),
93+
patch['width'],
94+
patch['height'],
95+
fill=False,
96+
color='r',
97+
linewidth=2
98+
)
99+
)
100+
plt.show()

0 commit comments

Comments
 (0)