Commit be66cf41 authored by Olegs NIKISINS's avatar Olegs NIKISINS

Fixed non-integer coordinates in array indexing in FaceDetector class

parent 60e00fe3
Pipeline #13588 passed with stages
in 9 minutes and 3 seconds
......@@ -19,16 +19,16 @@ 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.
Zhang, Kaipeng, et al. "Joint face detection and alignment using multitask cascaded convolutional networks." IEEE Signal Processing Letters 23.10 (2016): 1499-1503.
"""
def __init__(self):
"""
Load the caffe models
"""
caffe_base_path = FaceDetector.get_mtcnn_model_path()
# Default value from the example
......@@ -36,7 +36,7 @@ class FaceDetector(object):
self.threshold = [0.6, 0.7, 0.7]
self.factor = 0.709
self.fastresize = False
# 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)
......@@ -56,8 +56,8 @@ class FaceDetector(object):
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)
return landmarks
return landmarks
def detect_all_faces(self, image, return_bob_bb = True):
......@@ -70,29 +70,29 @@ class FaceDetector(object):
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
"""
assert image is not None
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)
# If there's no face, return none
if len(bb) == 0:
return None, None
if return_bob_bb:
bb = rectangle2bounding_box2(bb)
return bb, self._convert_list_to_landmarks(landmarks)
def detect_single_face(self, image):
"""
Returns the biggest face in a COLORED image, if any.
......@@ -104,14 +104,14 @@ class FaceDetector(object):
**Returns**
The face bounding box and its respective 5 landmarks (leye, reye, nose, mouthleft, mouthright).
If there's no face, `None` will be returned
"""
faces, landmarks = self.detect_all_faces(image)
# Return None if
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])
return faces[index], landmarks[index]
......@@ -120,56 +120,56 @@ class FaceDetector(object):
"""
Detects the biggest face and crop it based in the eyes location
using py:class:`bob.ip.base.FaceEyesNorm`.
Final eyes location was inspired here: https://gitlab.idiap.ch/bob/bob.bio.caffe_face/blob/master/bob/bio/caffe_face/config/preprocessor/vgg_preprocessor.py
**Parameters**
**Parameters**
image: numpy array with color image [c, w, h]
final_image_size: Image dimensions [w, h]
**Returns**
The cropped image. If there's no face, `None` will be returned
"""
face, landmark = self.detect_single_face(image)
if face is None:
return None
CROPPED_IMAGE_WIDTH = final_image_size[0]
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)
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):
"""
Detects the biggest face and crop it
**Parameters**
**Parameters**
image: numpy array with color image [c, w, h]
final_image_size: Image dimensions [w, h]
**Returns**
The cropped image. If there's no face, `None` will be returned
"""
face, landmark = self.detect_single_face(image)
if face is None:
return None
top = numpy.maximum(face.top - margin/2, 0)
left = 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.minimum(face.bottom + margin/2, image.shape[1])
right = 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]
......
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