-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathdaugman_visual_explanation.py
147 lines (122 loc) · 6.04 KB
/
daugman_visual_explanation.py
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
""" Code for `daugman_visual_explanation.ipynb`
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
import itertools
import random
from daugman import daugman
from daugman import find_iris
from typing import List, Tuple, Iterable
class DaugmanVisualExplanation:
def __init__(self, img_path: str, start_r=10, end_r=30, circle_step=2, points_step=3):
self.img = self._get_new_image(img_path)
self.start_r = start_r
self.end_r = end_r
self.circle_step = circle_step
self.points_step = points_step
self.all_points = self._get_all_potential_iris_centers(self.img)
self.colors = self._get_unique_color_for_each_point(self.all_points)
def _get_new_image(self, img_path, gray=False) -> np.ndarray:
""" Get properly cropped BGR image, which looks like grayscale
"""
img = cv2.imread(img_path)
img = img[20:130, 20:130]
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
if not gray:
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
return img
def _get_all_potential_iris_centers(self, img: np.ndarray) -> List[Tuple[int, int]]:
# get all potential points for search (from `find_iris()`)
h = img.shape[0]
# we will look only on dots within central 1/3 of image
single_axis_range = range(int(h / 3), h - int(h / 3), self.points_step)
all_points = list(itertools.product(single_axis_range, single_axis_range))
return all_points
def _get_unique_color_for_each_point(self, all_points: List[Tuple[int, int]]) -> List[Tuple[int, int, int]]:
colors = [(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) for i in self.all_points]
return colors
def plot_all_potential_iris_centers(self) -> np.ndarray:
# plot all potential points
img_dot = self.img.copy()
for point, color in zip(self.all_points, self.colors):
cv2.circle(img_dot, point, 0, color, -1)
_ = plt.imshow(img_dot[::, ::, ::-1])
return img_dot
def plot_circles_for_one_center(self, img_dot: np.ndarray, dot_idx=0) -> np.ndarray:
img_circles = img_dot.copy()
# within circles in radii range from 10px to 1/4 of image side
# plot the chosen potential point
cv2.circle(img_circles, list(self.all_points)[dot_idx], 0, self.colors[dot_idx], 1)
# plot all circle candidates for the single potential point
img_circles = self._draw_circles(img_circles, self.all_points[dot_idx], self.colors[dot_idx],
start_r=self.start_r, end_r=self.end_r, step=self.circle_step)
_ = plt.imshow(img_circles[::, ::, ::-1])
return img_circles
def _draw_circles(self, img: np.ndarray,
center: Tuple[int, int], color: Tuple[int, int, int],
start_r: int, end_r: int, step: int,
alpha=0.5) -> np.ndarray:
""" Part of ``daugman()`` modified for presentation purposes
"""
# get separate coordinates
x, y = center
overlay = img.copy()
radii = list(range(start_r, end_r, step))
for r in radii:
cv2.circle(overlay, center, r, color, 1)
img = cv2.addWeighted(overlay, alpha, img, 1 - alpha, 0)
return img
def plot_best_circle_for_single_potential_iris_center(self, img_dot: np.ndarray,
dot_idx: int, color=None, alpha=0.8) -> np.ndarray:
gray_img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
# get best circle
_, best_radius = daugman(gray_img, self.all_points[dot_idx],
self.start_r, self.end_r, self.circle_step)
# plot best circle
if not color:
color = self.colors[dot_idx]
overlay = img_dot.copy()
cv2.circle(overlay, self.all_points[dot_idx], best_radius, color, 1)
img_dot = cv2.addWeighted(overlay, alpha, img_dot, 1 - alpha, 0)
return img_dot
def plot_best_circle_for_a_few_potential_iris_centers(self, img_dot: np.ndarray,
idxs: Iterable[int]) -> np.ndarray:
img = img_dot.copy()
for idx in idxs:
img = self.plot_best_circle_for_single_potential_iris_center(img, idx)
_ = plt.imshow(img[::, ::, ::-1])
return img_dot
def find_iris(self, *, daugman_start, daugman_end, daugman_step, points_step) -> np.ndarray:
gray_img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
answer = find_iris(gray_img, daugman_start=daugman_start, daugman_end=daugman_end,
daugman_step=daugman_step, points_step=points_step)
iris_center, iris_rad = answer
out = self.img.copy()
cv2.circle(out, iris_center, iris_rad, (0, 0, 255), 1)
_ = plt.imshow(out[::, ::, ::-1])
return out
def plot_pixel_intensity_delta_pic(self) -> None:
# white image
img = np.full([100, 100, 3], 255, dtype=np.uint8)
# black circle
img = cv2.circle(img, (50, 50), 20, [0, 0, 0], -1)
# yellow
img = cv2.circle(img, (50, 50), 10, [255, 255, 0], 1)
# green
img = cv2.circle(img, (50, 50), 15, [0, 255, 0], 1)
# red
img = cv2.circle(img, (50, 50), 20, [255, 0, 0], 1)
# blue
img = cv2.circle(img, (50, 50), 25, [0, 0, 255], 1)
_ = plt.imshow(img)
def find_iris_on_binary_image(self, *, daugman_start, daugman_end, daugman_step, points_step) -> None:
# create simple image
img = np.full([100, 100, 3], 255, dtype=np.uint8)
img = cv2.circle(img, (50, 50), 20, [0, 0, 0], -1)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
answer = find_iris(gray_img, daugman_start=daugman_start, daugman_end=daugman_end,
daugman_step=daugman_step, points_step=points_step)
iris_center, iris_rad = answer
cv2.circle(img, iris_center, iris_rad, (0, 0, 255), 1)
_ = plt.imshow(img[::, ::, ::-1])