File size: 5,191 Bytes
b4c5d36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import os
import cv2
import numpy as np
from codes.base.core import (
    detections_to_rect,
    landmarks_to_detections,
    slice_from_roi,
    tflite_inference,
    transform_rect,
)


PATH2ROOT_ABS = os.path.dirname(__file__) + "/../../"


def from_landmarks_to_depth(

    frame_rgb, eye_landmarks, image_size, is_right_eye=False, focal_length=None

):
    """

    Predicting the iris position using eyes landmarks



    Parameters:

        frame_rgb: the frame (RGB)

        eye_landmarks: the landmarks of the eyes

        image_size: the image size

        is_right_eye: whether or not it's the right eye

        focal_length: the focal length of the camera



    Returns:

        success: whether or not the iris is detected

        depth: distance to the camera

        iris_size: the size of the iris

        iris_landmarks: iris landmarks

        eye_contours: eye contours

        iris_landmarks_respect: iris landmarks respect to the eyes

    """
    if focal_length is None:
        focal_length = frame_rgb.shape[1]

    detections = landmarks_to_detections(eye_landmarks)
    rect = detections_to_rect(detections, image_size, rotation_vector_start_end=(0, 1))
    roi = transform_rect(rect, image_size, scale_x=2.3, scale_y=2.3)

    slice_y = slice_from_roi(roi, image_size, False)
    slice_x = slice_from_roi(roi, image_size, True)
    eye_image = frame_rgb[slice(*slice_y), slice(*slice_x), :]
    position_in_frame = np.array((slice_x[0], slice_y[0], 0))

    if eye_image.any():
        success = True
        eye_contours, iris_landmarks, eye_frame_low = detect_iris(
            eye_image.copy(), is_right_eye=is_right_eye
        )

        iris_landmarks_respect = iris_landmarks.copy()

        eye_contours[:, 0] = eye_contours[:, 0] * eye_image.shape[0]
        eye_contours[:, 1] = eye_contours[:, 1] * eye_image.shape[1]
        eye_contours = eye_contours + position_in_frame

        eye_contours[:, 0] = eye_contours[:, 0] / frame_rgb.shape[1]
        eye_contours[:, 1] = eye_contours[:, 1] / frame_rgb.shape[0]

        iris_landmarks[:, 0] = iris_landmarks[:, 0] * eye_image.shape[0]
        iris_landmarks[:, 1] = iris_landmarks[:, 1] * eye_image.shape[1]
        iris_landmarks = iris_landmarks + position_in_frame

        iris_landmarks[:, 0] = iris_landmarks[:, 0] / frame_rgb.shape[1]
        iris_landmarks[:, 1] = iris_landmarks[:, 1] / frame_rgb.shape[0]

        depth, iris_size = calculate_iris_depth(iris_landmarks, image_size, focal_length)
        
    else:
        success = False
        depth = None
        iris_size = None
        iris_landmarks = None
        eye_contours = None
        iris_landmarks_respect = None

    return success, depth, iris_size, iris_landmarks, eye_contours, iris_landmarks_respect


def detect_iris(eye_frame, is_right_eye=False):
    side_low = 64
    eye_frame_low = cv2.resize(
        eye_frame, (side_low, side_low), interpolation=cv2.INTER_AREA
    )

    model_path = PATH2ROOT_ABS + "models/iris/iris_landmark.tflite"

    if is_right_eye:
        eye_frame_low = np.fliplr(eye_frame_low)

    outputs = tflite_inference(eye_frame_low / 127.5 - 1.0, model_path)
    eye_contours_low = np.reshape(outputs[0], (71, 3))
    iris_landmarks_low = np.reshape(outputs[1], (5, 3))

    eye_contours = eye_contours_low / side_low
    iris_landmarks = iris_landmarks_low / side_low

    if is_right_eye:
        eye_contours[:, 0] = 1 - eye_contours[:, 0]
        iris_landmarks[:, 0] = 1 - iris_landmarks[:, 0]

    return eye_contours, iris_landmarks, eye_frame_low


def calculate_iris_depth(iris_landmarks, image_size, focal_length_pixel):
    """

    iris_landmarks should be normalized to the complete image frame

    depth in mm

    """
    iris_size = calculate_iris_diameter(iris_landmarks, image_size)
    depth = calculate_depth(
        iris_landmarks[0, :], focal_length_pixel, iris_size, image_size
    )

    return depth, iris_size


def get_depth(x0, y0, x1, y1):
    return np.sqrt((x0 - x1) ** 2 + (y0 - y1) ** 2)


def get_landmark_depth(ld0, ld1, image_size):
    return get_depth(
        ld0[0] * image_size[0],
        ld0[1] * image_size[1],
        ld1[0] * image_size[0],
        ld1[1] * image_size[1],
    )


def calculate_iris_diameter(iris_landmarks, image_size):
    dist_vert = get_landmark_depth(
        iris_landmarks[1, :], iris_landmarks[3, :], image_size
    )
    dist_hori = get_landmark_depth(
        iris_landmarks[2, :], iris_landmarks[4, :], image_size
    )

    return (dist_hori + dist_vert) / 2.0


def calculate_depth(center_landmark, focal_length_pixel, iris_size, image_size):
    # Average fixed iris size across human beings.
    human_iris_size_in_mm = 11.8
    origin = np.array(image_size) / 2.0
    center_landmark_pixel = center_landmark[:2] * np.array(image_size)
    y = get_depth(
        origin[0], origin[1], center_landmark_pixel[0], center_landmark_pixel[1]
    )
    x = np.sqrt(focal_length_pixel ** 2 + y ** 2)
    depth = human_iris_size_in_mm * x / iris_size

    return depth