Commit 44805cae authored by Amir MOHAMMADI's avatar Amir MOHAMMADI

Merge branch 'cleanup' into 'master'

Clean-up

See merge request !3
parents 7d5ee056 a24be2ea
Pipeline #14164 passed with stages
in 8 minutes and 44 seconds
......@@ -17,11 +17,16 @@ from bob.ip.facedetect import BoundingBox
from .legacy import detect_face
from .utils import bob_to_dlib_image_convertion, rectangle2bounding_box2
class FaceDetector(object):
"""
Detects face and 5 landmarks using the MTCNN (https://github.com/kpzhang93/MTCNN_face_detection_alignment) from the paper.
Detects face and 5 landmarks using the MTCNN
(https://github.com/kpzhang93/MTCNN_face_detection_alignment) from the
paper.
Zhang, Kaipeng, et al. "Joint face detection and alignment using multitask cascaded convolutional networks." IEEE Signal Processing Letters 23.10 (2016): 1499-1503.
Zhang, Kaipeng, et al. "Joint face detection and alignment using multitask
cascaded convolutional networks." IEEE Signal Processing Letters 23.10
(2016): 1499-1503.
"""
......@@ -40,10 +45,15 @@ class FaceDetector(object):
# Loading the models
caffe.set_mode_cpu()
self.p_net = caffe.Net(os.path.join(caffe_base_path, "det1.prototxt"), os.path.join(caffe_base_path, "det1.caffemodel"), caffe.TEST)
self.r_net = caffe.Net(os.path.join(caffe_base_path, "det2.prototxt"), os.path.join(caffe_base_path, "det2.caffemodel"), caffe.TEST)
self.o_net = caffe.Net(os.path.join(caffe_base_path, "det3.prototxt"), os.path.join(caffe_base_path, "det3.caffemodel"), caffe.TEST)
self.p_net = caffe.Net(
os.path.join(caffe_base_path, "det1.prototxt"),
os.path.join(caffe_base_path, "det1.caffemodel"), caffe.TEST)
self.r_net = caffe.Net(
os.path.join(caffe_base_path, "det2.prototxt"),
os.path.join(caffe_base_path, "det2.caffemodel"), caffe.TEST)
self.o_net = caffe.Net(
os.path.join(caffe_base_path, "det3.prototxt"),
os.path.join(caffe_base_path, "det3.caffemodel"), caffe.TEST)
def _convert_list_to_landmarks(self, points):
"""
......@@ -51,38 +61,51 @@ class FaceDetector(object):
"""
landmarks = []
possible_landmarks = ['reye', 'leye', 'nose', 'mouthleft', 'mouthright']
possible_landmarks = ['reye', 'leye',
'nose', 'mouthleft', 'mouthright']
for i in range(points.shape[0]):
l = dict()
for offset, p in zip(range(len(possible_landmarks)), possible_landmarks):
l[p] = ( int(points[i][offset+5]), int(points[i][offset]) )
landmarks.append(l)
landmark = dict()
for offset, p in enumerate(possible_landmarks):
landmark[p] = (int(points[i][offset + 5]),
int(points[i][offset]))
landmarks.append(landmark)
return landmarks
def detect_all_faces(self, image, return_bob_bb = True):
def detect_all_faces(self, image, return_bob_bb=True):
"""
Detect all the faces with its respective landmarks, if any, in a COLORED image
**Parameters**
image: numpy array with color image [c, w, h]
return_bob_bb: if true will return the faces wrapped using py:class:`bob.ip.facedetect.BoundingBox`
**Returns**
Returns two lists; the first on contains the bounding boxes with the detected faces and the second one
contains list with the faces landmarks. The CNN returns 5 facial landmarks
(leye, reye, nose, mouthleft, mouthright). If there's no face, `None` will be returned
Detect all the faces with its respective landmarks, if any, in a
COLORED image
Parameters
----------
image : numpy.array
The color image [c, w, h]
return_bob_bb : bool, optional
If true, will return faces wrapped using
:any:`bob.ip.facedetect.BoundingBox`.
Returns
-------
object
Returns two lists; the first on contains the bounding boxes with
the detected faces and the second one contains list with the faces
landmarks. The CNN returns 5 facial landmarks (leye, reye, nose,
mouthleft, mouthright). If there's no face, `None` will be returned
Raises
------
ValueError
When image.ndim is not 3.
"""
assert image is not None
if len(image.shape) !=3:
if len(image.shape) != 3:
raise ValueError("Only color images is supported")
bb, landmarks = detect_face(bob_to_dlib_image_convertion(image), self.minsize, self.p_net, self.r_net, self.o_net, self.threshold, self.fastresize, self.factor)
bb, landmarks = detect_face(bob_to_dlib_image_convertion(
image), self.minsize, self.p_net, self.r_net, self.o_net, self.threshold, self.fastresize, self.factor)
# If there's no face, return none
if len(bb) == 0:
......@@ -93,18 +116,19 @@ class FaceDetector(object):
return bb, self._convert_list_to_landmarks(landmarks)
def detect_single_face(self, image):
"""
Returns the biggest face in a COLORED image, if any.
**Parameters**
image: numpy array with color image [c, w, h]
return_bob_bb: if true will return the faces wrapped using py:class:`bob.ip.facedetect.BoundingBox`
Parameters
----------
image : numpy.array
numpy array with color image [c, w, h]
**Returns**
The face bounding box and its respective 5 landmarks (leye, reye, nose, mouthleft, mouthright).
If there's no face, `None` will be returned
Returns
-------
The face bounding box and its respective 5 landmarks (leye, reye, nose,
mouthleft, mouthright). If there's no face, `None` will be returned
"""
......@@ -113,11 +137,12 @@ class FaceDetector(object):
if faces is None:
return None, None
index = numpy.argmax([(f.bottomright[0] - f.topleft[0]) * (f.bottomright[1] - f.topleft[1]) for f in faces])
index = numpy.argmax([(f.bottomright[0] - f.topleft[0])
* (f.bottomright[1] - f.topleft[1]) for f in faces])
return faces[index], landmarks[index]
def detect_crop_align(self, image, final_image_size=(160, 160) ):
def detect_crop_align(self, image, final_image_size=(160, 160)):
"""
Detects the biggest face and crop it based in the eyes location
using py:class:`bob.ip.base.FaceEyesNorm`.
......@@ -142,10 +167,13 @@ class FaceDetector(object):
CROPPED_IMAGE_HEIGHT = final_image_size[1]
# final image position w.r.t the image size
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT / 3.44, CROPPED_IMAGE_WIDTH / 3.02)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT / 3.44 , CROPPED_IMAGE_WIDTH / 1.49)
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT / 3.44,
CROPPED_IMAGE_WIDTH / 3.02)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT / 3.44,
CROPPED_IMAGE_WIDTH / 1.49)
extractor = bob.ip.base.FaceEyesNorm((CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH), RIGHT_EYE_POS, LEFT_EYE_POS)
extractor = bob.ip.base.FaceEyesNorm(
(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH), RIGHT_EYE_POS, LEFT_EYE_POS)
return extractor(image, landmark['reye'], landmark['leye'])
def detect_crop(self, image, final_image_size=(182, 182), margin=44):
......@@ -166,11 +194,13 @@ class FaceDetector(object):
if face is None:
return None
top = numpy.uint(numpy.maximum(face.top - margin/2, 0))
left = numpy.uint(numpy.maximum(face.left - margin/2, 0))
top = numpy.uint(numpy.maximum(face.top - margin / 2, 0))
left = numpy.uint(numpy.maximum(face.left - margin / 2, 0))
bottom = numpy.uint(numpy.minimum(face.bottom + margin/2, image.shape[1]))
right = numpy.uint(numpy.minimum(face.right + margin/2, image.shape[2]))
bottom = numpy.uint(numpy.minimum(
face.bottom + margin / 2, image.shape[1]))
right = numpy.uint(numpy.minimum(
face.right + margin / 2, image.shape[2]))
cropped = image[:, top:bottom, left:right]
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment