예제 #1
0
def get_cropped_face_using_fixed_eye_pos(
        image_path, align_path, offset_pct, dest_size):
    """
    Get face cropped and aligned to eyes from image file
    Eye positions are known and corresponds to intersection in grid

    :type image_path: string
    :param image_path: path of image to be cropped

    :type align_path: string
    :param align_path: path of directory where aligned faces are saved

    :type offset_pct: 2-element tuple
    :param offset_pct: offset given as percentage of eye-to-eye distance

    :type dest_size: 2-element tuple
    :param dest_size: size of result

    :rtype: OpenCV image or None
    :returns: face
    """

    cropped_image = None
    # Open image
    file_check = os.path.isfile(image_path)

    if not file_check:
        print('File does not exist')
        return
    try:
        # Open whole image as PIL Image
        img = Image.open(image_path)

        # Align face image
        (width, height) = img.size

        eye_left = (width / c.GRID_CELLS_X, height / c.GRID_CELLS_Y)

        eye_right = (2 * width / c.GRID_CELLS_Y, height / c.GRID_CELLS_Y)

        # Create unique file path

        tmp_file_name = str(uuid.uuid4()) + '.png'
        tmp_file_path = os.path.join(align_path, tmp_file_name)

        CropFace(
            img, eye_left, eye_right, offset_pct, dest_size).save(tmp_file_path)

        face_image = cv2.imread(tmp_file_path, cv2.IMREAD_GRAYSCALE)

        if c.USE_HIST_EQ_IN_CROPPED_FACES:
            face_image = cv2.equalizeHist(face_image)

        if c.USE_NORM_IN_CROPPED_FACES:
            face_image = cv2.normalize(
                face_image, alpha=0, beta=255,
                norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)

        if c.USE_CANNY_IN_CROPPED_FACES:
            face_image = cv2.Canny(face_image, 0.1, 100)

        if c.USE_TAN_AND_TRIGG_NORM:
            face_image = utils.normalize_illumination(face_image)

        # Insert oval mask in image
        if c.USE_OVAL_MASK:
            face_image = utils.add_oval_mask(face_image)

        return face_image

    except IOError, (errno, strerror):
        print "I/O error({0}): {1}".format(errno, strerror)
예제 #2
0
def get_cropped_face_from_image(
        image, image_path, align_path, params, eye_cascade_classifier,
        nose_cascade_classifier, face_bbox, delete_files, return_always_face):
    """
    Get face cropped and aligned to eyes from image

    :type image: openCV image
    :param image: image to be cropped

    :type image_path: string
    :param image_path: path of image to be analyzed

    :type align_path: string
    :param align_path: path of directory where aligned faces are saved

    :type params: dictionary
    :param params: dictionary containing the parameters
    to be used for the face detection

    :type eye_cascade_classifier: CascadeClassifier
    :param eye_cascade_classifier: classifier for detecting eyes

    :type nose_cascade_classifier: CascadeClassifier
    :param nose_cascade_classifier: classifier for detecting nose

    :type face_bbox: tuple
    :type face_bbox: bbox of face in original image,
    represented as (x, y, width, height)

    :type delete_files: boolean
    :param delete_files: delete(true) or do not delete(false)
    saved image files

    :type return_always_face: boolean
    :type return_always_face: if true,
    return face even if no eyes are detected

    :rtype: dictionary or None
    :returns: dictionary with results
    """

    result = {}

    # Offset given as percentage of eye-to-eye distance
    offset_pct_x = c.OFFSET_PCT_X
    offset_pct_y = c.OFFSET_PCT_Y

    # Final size of cropped face
    cropped_face_width = c.CROPPED_FACE_WIDTH
    cropped_face_height = c.CROPPED_FACE_HEIGHT

    # If True, check eye positions
    check_eye_positions = c.CHECK_EYE_POSITIONS

    if params is not None:
        if c.CROPPED_FACE_WIDTH_KEY in params:
            cropped_face_width = params[c.CROPPED_FACE_WIDTH_KEY]
        if c.CROPPED_FACE_HEIGHT_KEY in params:
            cropped_face_height = params[c.CROPPED_FACE_HEIGHT_KEY]
        if c.OFFSET_PCT_X_KEY in params:
            offset_pct_x = params[c.OFFSET_PCT_X_KEY]
        if c.OFFSET_PCT_Y_KEY in params:
            offset_pct_y = params[c.OFFSET_PCT_Y_KEY]
        if c.CHECK_EYE_POSITIONS_KEY in params:
            check_eye_positions = params[c.CHECK_EYE_POSITIONS_KEY]

    offset_pct = (offset_pct_x, offset_pct_y)

    dest_size = (cropped_face_width, cropped_face_height)

    # Detect eyes in face
    eye_rects = utils.detect_eyes_in_image(image, eye_cascade_classifier)

    eye_left = None

    eye_right = None

    eye_check_ok = False

    if len(eye_rects) == 2:

        x_first_eye = eye_rects[0][0]
        y_first_eye = eye_rects[0][1]
        w_first_eye = eye_rects[0][2]
        h_first_eye = eye_rects[0][3]

        x_second_eye = eye_rects[1][0]
        y_second_eye = eye_rects[1][1]
        w_second_eye = eye_rects[1][2]
        h_second_eye = eye_rects[1][3]

        x_left_eye_center = 0
        y_left_eye_center = 0
        x_right_eye_center = 0
        y_right_eye_center = 0
        if x_first_eye < x_second_eye:
            x_left_eye_center = x_first_eye + w_first_eye / 2
            y_left_eye_center = y_first_eye + h_first_eye / 2

            x_right_eye_center = x_second_eye + w_second_eye / 2
            y_right_eye_center = y_second_eye + h_second_eye / 2
        else:
            x_right_eye_center = x_first_eye + w_first_eye / 2
            y_right_eye_center = y_first_eye + h_first_eye / 2

            x_left_eye_center = x_second_eye + w_second_eye / 2
            y_left_eye_center = y_second_eye + h_second_eye / 2

        eye_left = (int(x_left_eye_center + face_bbox[0]),
                    int(y_left_eye_center + face_bbox[1]))
        eye_right = (int(x_right_eye_center + face_bbox[0]),
                     int(y_right_eye_center + face_bbox[1]))

        if check_eye_positions:
            eye_check_ok = utils.check_eye_pos(
                eye_left, eye_right, face_bbox, params)
        else:
            eye_check_ok = True

    if eye_check_ok:

        # Open whole image as PIL Image
        img = Image.open(image_path)

        # Store eye positions related to whole image
        result[c.LEFT_EYE_POS_KEY] = eye_left
        result[c.RIGHT_EYE_POS_KEY] = eye_right

        result[c.NOSE_POSITION_KEY] = None

        # Align face image

        # Create unique file path

        tmp_file_name = str(uuid.uuid4())
        tmp_file_name_complete = tmp_file_name + '.png'
        tmp_file_path = os.path.join(align_path, tmp_file_name_complete)

        CropFace(
            img, eye_left, eye_right, offset_pct, dest_size).save(tmp_file_path)

        face_image = cv2.imread(tmp_file_path, cv2.IMREAD_GRAYSCALE)

        if delete_files:
            os.remove(tmp_file_path)
        else:
            result[c.ALIGNED_FACE_FILE_NAME_KEY] = tmp_file_name

        # Check nose position
        nose_check_ok = True

        use_nose_pos_in_detection = c.USE_NOSE_POS_IN_DETECTION
        use_nose_pos_in_recognition = c.USE_NOSE_POS_IN_RECOGNITION

        if params is not None:
            if c.USE_NOSE_POS_IN_DETECTION_KEY in params:
                use_nose_pos_in_detection = params[c.USE_NOSE_POS_IN_DETECTION_KEY]
            if c.USE_NOSE_POS_IN_RECOGNITION_KEY in params:
                use_nose_pos_in_recognition = params[c.USE_NOSE_POS_IN_RECOGNITION_KEY]

        if use_nose_pos_in_detection or use_nose_pos_in_recognition:

            noses = utils.detect_nose_in_image(
                face_image, nose_cascade_classifier)

            x_right_eye = offset_pct[0] * dest_size[0]
            x_left_eye = dest_size[0] - x_right_eye
            y_eyes = offset_pct[1] * dest_size[1]

            good_noses = 0

            for(x_nose, y_nose, w_nose, h_nose) in noses:

                # Coordinates of bounding box center in face image
                x_center = float(x_nose + w_nose / 2)
                y_center = float(y_nose + h_nose / 2)

                # Store nose position relative to face image
                nose_x_pct = x_center / cropped_face_width
                nose_y_pct = y_center / cropped_face_height
                nose = (nose_x_pct, nose_y_pct)
                result[c.NOSE_POSITION_KEY] = nose

                # Nose must be between eyes in horizontal direction
                # and below eyes in vertical direction
                if((x_center > x_right_eye) and(x_center < x_left_eye)
                        and (y_center > y_eyes)):
                    good_noses += 1

            if good_noses != 1:

                nose_check_ok = False
                result[c.NOSE_POSITION_KEY] = None

        if nose_check_ok or not use_nose_pos_in_detection:
            if c.USE_HIST_EQ_IN_CROPPED_FACES:
                face_image = cv2.equalizeHist(face_image)
            if c.USE_NORM_IN_CROPPED_FACES:
                face_image = cv2.normalize(
                    face_image, alpha=0, beta=255,
                    norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
            if c.USE_CANNY_IN_CROPPED_FACES:
                face_image = cv2.Canny(face_image, 0.1, 100)
            if c.USE_TAN_AND_TRIGG_NORM:
                face_image = utils.normalize_illumination(face_image)
            # Insert oval mask in image
            if c.USE_OVAL_MASK:
                face_image = utils.add_oval_mask(face_image)

            if not delete_files:
                tmp_file_name_gray = (
                    tmp_file_name + c.ALIGNED_FACE_GRAY_SUFFIX + '.png')
                tmp_file_gray_path = os.path.join(
                    align_path, tmp_file_name_gray)

                cv2.imwrite(tmp_file_gray_path, face_image)

            return result

        else:

            result[c.FACE_KEY] = None

            return result

    else:

        if return_always_face:
            result[c.LEFT_EYE_POS_KEY] = None
            result[c.RIGHT_EYE_POS_KEY] = None
            return result

        else:

            return None