Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/Face-Recognition-with-ArcFace/tsne.py
3118 views
1
import argparse
2
import os
3
import random
4
5
import cv2
6
import matplotlib.pyplot as plt
7
import numpy as np
8
import torch
9
from embeddings import get_embeddings
10
from sklearn.manifold import TSNE
11
from tqdm import tqdm
12
13
14
def fix_random_seeds():
15
seed = 10
16
random.seed(seed)
17
torch.manual_seed(seed)
18
np.random.seed(seed)
19
20
21
# scale and move the coordinates so they fit [0; 1] range
22
def scale_to_01_range(x):
23
# compute the distribution range
24
value_range = np.max(x) - np.min(x)
25
26
# move the distribution so that it starts from zero
27
# by extracting the minimal value from all its values
28
starts_from_zero = x - np.min(x)
29
30
# make the distribution fit [0; 1] by dividing by its range
31
return starts_from_zero / value_range
32
33
34
def scale_image(image, max_image_size):
35
image_height, image_width, _ = image.shape
36
37
scale = max(1, image_width / max_image_size, image_height / max_image_size)
38
image_width = int(image_width / scale)
39
image_height = int(image_height / scale)
40
41
image = cv2.resize(image, (image_width, image_height))
42
return image
43
44
45
def compute_plot_coordinates(image, x, y, image_centers_area_size, offset):
46
image_height, image_width, _ = image.shape
47
48
# compute the image center coordinates on the plot
49
center_x = int(image_centers_area_size * x) + offset
50
51
# in matplotlib, the y axis is directed upward
52
# to have the same here, we need to mirror the y coordinate
53
center_y = int(image_centers_area_size * (1 - y)) + offset
54
55
# knowing the image center, compute the coordinates of the top left and bottom right corner
56
tl_x = center_x - int(image_width / 2)
57
tl_y = center_y - int(image_height / 2)
58
59
br_x = tl_x + image_width
60
br_y = tl_y + image_height
61
62
return tl_x, tl_y, br_x, br_y
63
64
65
def visualize_tsne_images(tx, ty, images, plot_size=1000, max_image_size=100):
66
# we'll put the image centers in the central area of the plot
67
# and use offsets to make sure the images fit the plot
68
offset = max_image_size // 2
69
image_centers_area_size = plot_size - 2 * offset
70
71
tsne_plot = 255 * np.ones((plot_size, plot_size, 3), np.uint8)
72
73
# now we'll put a small copy of every image to its corresponding T-SNE coordinate
74
for image, x, y in tqdm(
75
zip(images, tx, ty), desc="Building the T-SNE plot", total=len(images),
76
):
77
78
# scale the image to put it to the plot
79
image = scale_image(image, max_image_size)
80
81
# compute the coordinates of the image on the scaled plot visualization
82
tl_x, tl_y, br_x, br_y = compute_plot_coordinates(
83
image, x, y, image_centers_area_size, offset,
84
)
85
86
# put the image to its TSNE coordinates using numpy subarray indices
87
tsne_plot[tl_y:br_y, tl_x:br_x, :] = image
88
89
plt.figure('Embeddings projection with t-SNE')
90
plt.axis('off')
91
plt.imshow(tsne_plot[:, :, ::-1])
92
plt.savefig('tsne_plot.jpg')
93
plt.show()
94
95
96
def visualize_tsne(tsne, images, plot_size=1000, max_image_size=100):
97
# extract x and y coordinates representing the positions of the images on T-SNE plot
98
tx = tsne[:, 0]
99
ty = tsne[:, 1]
100
101
# scale and move the coordinates so they fit [0; 1] range
102
tx = scale_to_01_range(tx)
103
ty = scale_to_01_range(ty)
104
105
# visualize the plot: samples as images
106
visualize_tsne_images(
107
tx, ty, images, plot_size=plot_size, max_image_size=max_image_size,
108
)
109
110
111
def main():
112
parser = argparse.ArgumentParser()
113
parser.add_argument(
114
"--tags",
115
help="specify your tags for aligned faces datasets",
116
default="test",
117
nargs='+',
118
required=True
119
)
120
args = parser.parse_args()
121
tags = args.tags
122
parser.add_argument(
123
"--input_size",
124
help="specify size of aligned faces, align and crop with padding",
125
default=112,
126
choices=[112, 224],
127
type=int,
128
)
129
args = parser.parse_args()
130
131
fix_random_seeds()
132
133
# predict embeddings for each small dataset
134
all_images = []
135
all_embeddings = []
136
tags = args.tags
137
input_size = args.input_size
138
for tag in tags:
139
images, embeddings = get_embeddings(
140
data_root=f"data/{tag}_aligned",
141
model_root="checkpoint/backbone_ir50_ms1m_epoch120.pth",
142
input_size=[input_size, input_size],
143
)
144
all_images.append(images)
145
all_embeddings.append(embeddings)
146
147
# concatenate images and embeddings from different persons into matrices
148
all_images = np.vstack(all_images)
149
all_embeddings = np.vstack(all_embeddings)
150
# perplexity is lower than default, because number of samples is small
151
tsne_results = TSNE(n_components=2, perplexity=8).fit_transform(all_embeddings)
152
visualize_tsne(tsne_results, all_images, plot_size=1000, max_image_size=112)
153
154
155
if __name__ == "__main__":
156
fix_random_seeds()
157
main()
158
159