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
|