def enumerate_faces(self, img, resize_wh=128):
        # Padding the image
        img = cv2.copyMakeBorder(img,
                                 PAD,
                                 PAD,
                                 PAD,
                                 PAD,
                                 cv2.BORDER_CONSTANT,
                                 value=255)
        grey = rgb2grey(img)

        # Larger faces has higher priority to solve the problem one person
        # detected as two or more faces
        faces = self.face_cascade.detectMultiScale(grey, 1.3, 5)
        faces = sorted(faces, key=lambda tup: tup[2], reverse=True)

        for face in faces:
            aligned_face = self.face_align(grey, face)
            aligned_face = cv2.bilateralFilter(aligned_face, 0, 5, 2)
            equaliser = cv2.createCLAHE(clipLimit=1.5)
            aligned_face = equaliser.apply(aligned_face)
            resized_aligned_face = cv2.resize(aligned_face,
                                              (resize_wh, resize_wh),
                                              interpolation=cv2.INTER_CUBIC)
            # remove the PAD pixels we put in around the main image so
            # coordinates are right
            unpad_face = (face[0] - PAD, face[1] - PAD, face[2], face[3])

            # give back position (for plotting) and cropped image
            yield unpad_face, resized_aligned_face
def img2vec(img):
    """Convert a 2D image into a flat vector."""
    assert 2 <= img.ndim <= 3, "Image must be 2D grey or RGB"
    assert img.shape[0] == img.shape[1], "Image must be square"
    img = rgb2grey(im2double(img))
    assert img.ndim == 2, \
        "Need grey image; got array with shape {}".format(img.shape)
    return img.flatten()
 def __call__(self, image):
     assert 2 <= image.ndim <= 3, \
         "Expecting 2D or 3D image, got shape %s" % (image.shape,)
     if image.ndim == 2:
         rv = rgb2grey(image)
     else:
         rv = image
     if self.trailing_dim and rv.ndim < 3:
         # add a singleton dimension on the end
         rv = rv[..., None]
     return rv
Beispiel #4
0
          (args.input_dir, args.output_dir))
    try:
        os.makedirs(args.output_dir)
    except FileExistsError:
        pass
    input_dir = os.path.abspath(args.input_dir)
    image_paths = get_paths(input_dir)
    pipe = FacePipe()
    for num, input_path in enumerate(image_paths, start=1):
        filename = os.path.basename(input_path)
        input_path_dirname = os.path.dirname(input_path)
        subdir = input_path_dirname[len(input_dir):]
        subdir = subdir.lstrip(os.path.sep)
        output_subdir = os.path.join(args.output_dir, subdir)
        os.makedirs(output_subdir, exist_ok=True)
        output_path = os.path.join(output_subdir, filename)
        print('\n%d. Processing "%s", storing in "%s"' %
              (num, input_path, output_path))
        im = imread(input_path)
        faces = list(pipe.enumerate_faces(im, args.size))
        if len(faces) == 0:
            print("Didn't detect any faces (!); not cropping at all")
            # this will stretch faces sometimes
            out_im = imresize(im, (args.size, args.size))
        else:
            if len(faces) > 1:
                print('Got %d faces; using the first only' % len(faces))
            _, out_im = faces[0]
        out_im = rgb2grey(out_im)
        imsave(output_path, out_im)
    def face_align(self, img, face):

        image_width = np.size(img, 1)
        image_height = np.size(img, 0)
        (x, y, w, h) = face

        # Get Target eye width
        # EYEW_TARGET_RATIO = .25
        EYEW_TARGET_RATIO = .25
        EYEW_TARGET = h * EYEW_TARGET_RATIO

        # Get target mouth and eye height
        MOUTH_EYE_TARGET_RATIO = .19
        MOUTH_EYE_TARGET = h * MOUTH_EYE_TARGET_RATIO

        # Get target nose and eye height
        NOSE_EYE_TARGET_RATIO = .12
        NOSE_EYE_TARGET = h * NOSE_EYE_TARGET_RATIO

        grey = rgb2grey(img)
        roi_grey = crop(grey, x, y, w, h)

        eye_pair = self._getEyePair(roi_grey)
        lEye, rEye = self._getEyes(roi_grey, face, eye_pair)
        mouth = self._getMouth(roi_grey)
        nose = self._getNose(roi_grey)

        # cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # If two eyes are detected

        if lEye is not None and rEye is not None:
            eyeAngle = np.degrees(
                np.arctan((rEye.center[1] - lEye.center[1]) /
                          (rEye.center[0] - lEye.center[0])))
            mid_eye = np.mean([lEye.center, rEye.center], axis=0)
            eye_width = np.linalg.norm(lEye.center - rEye.center)

        # if not two eyes are detected
        else:
            eyeAngle = 0
            if eye_pair is not None:
                mid_eye = eye_pair.center
                eye_width = eye_pair.w * EYEPAIR_WIDTH_TO_EYE_WIDTH
            else:
                mid_eye = np.array([w * EYE_RATIO_WIDTH, h * EYE_RATIO_HEIGHT])
                eye_width = w * FACE_WIDTH_TO_EYE_WIDTH

        # Convert relative coordinate to absolute coordinate
        mid_eye_x = mid_eye[0] + x
        mid_eye_y = mid_eye[1] + y

        mouth_eye_dist = 0

        if mouth is not None:
            mouth_eye_dist = np.linalg.norm(mouth.center - mid_eye)

        nose_eye_dist = 0
        if nose is not None:
            nose_eye_dist = np.linalg.norm(nose.center - mid_eye)

        # Get the maximal width and height based on the eyewidth,
        # mouth_eye_distance and nose_eye_distance
        new_w = max(int((eye_width / EYEW_TARGET) * w),
                    int((mouth_eye_dist / MOUTH_EYE_TARGET) * w),
                    int((nose_eye_dist / NOSE_EYE_TARGET) * w))
        new_h = max(int((eye_width / EYEW_TARGET) * h),
                    int((mouth_eye_dist / MOUTH_EYE_TARGET) * h),
                    int((nose_eye_dist / NOSE_EYE_TARGET) * h))

        # Get homography matrix
        pts_src = np.array([[x, y], [x + w, y], [x, y + h], [x + w, y + h]])
        pts_dst = np.array([[
            mid_eye_x - new_w * EYE_RATIO_WIDTH,
            mid_eye_y - new_h * EYE_RATIO_HEIGHT
        ],
                            [
                                mid_eye_x + new_w * (1 - EYE_RATIO_WIDTH),
                                mid_eye_y - new_h * EYE_RATIO_HEIGHT
                            ],
                            [
                                mid_eye_x - new_w * EYE_RATIO_WIDTH,
                                mid_eye_y + new_h * (1 - EYE_RATIO_HEIGHT)
                            ],
                            [
                                mid_eye_x + new_w * (1 - EYE_RATIO_WIDTH),
                                mid_eye_y + new_h * (1 - EYE_RATIO_HEIGHT)
                            ]])

        h**o, status = cv2.findHomography(pts_src, pts_dst)
        img = cv2.warpPerspective(img, h**o, (image_width, image_height))

        # Rotation
        if eyeAngle != 0:
            rotMatrix = cv2.getRotationMatrix2D((mid_eye_x, mid_eye_y),
                                                eyeAngle, 1)
            img = cv2.warpAffine(img, rotMatrix, (image_width, image_height))

        return crop(img, int(mid_eye_x - new_w * EYE_RATIO_WIDTH),
                    int(mid_eye_y - new_h * EYE_RATIO_HEIGHT), new_w, new_h)