|
import numpy as np |
|
import os |
|
import cv2 |
|
import matplotlib.pyplot as plt |
|
from scipy.ndimage import zoom |
|
|
|
|
|
def print_training_params_to_file(init_locals): |
|
"""save param log file""" |
|
|
|
del init_locals['self'] |
|
with open(os.path.join(init_locals['save_log_path'], 'Training_Parameters.txt'), 'w') as f: |
|
f.write('Training Parameters:\n\n') |
|
for key, value in init_locals.items(): |
|
f.write('* %s: %s\n' % (key, value)) |
|
|
|
|
|
def heat_maps_to_landmarks(maps, image_size=256, num_landmarks=68): |
|
"""find landmarks from heatmaps (arg max on each map)""" |
|
|
|
landmarks = np.zeros((num_landmarks,2)).astype('float32') |
|
|
|
for m_ind in range(num_landmarks): |
|
landmarks[m_ind, :] = np.unravel_index(maps[:, :, m_ind].argmax(), (image_size, image_size)) |
|
|
|
return landmarks |
|
|
|
|
|
def heat_maps_to_landmarks_alloc_once(maps, landmarks, image_size=256, num_landmarks=68): |
|
"""find landmarks from heatmaps (arg max on each map) with pre-allocation""" |
|
|
|
for m_ind in range(num_landmarks): |
|
landmarks[m_ind, :] = np.unravel_index(maps[:, :, m_ind].argmax(), (image_size, image_size)) |
|
|
|
|
|
def batch_heat_maps_to_landmarks_alloc_once(batch_maps, batch_landmarks, batch_size, image_size=256, num_landmarks=68): |
|
"""find landmarks from heatmaps (arg max on each map) - for multiple images""" |
|
|
|
for i in range(batch_size): |
|
heat_maps_to_landmarks_alloc_once( |
|
maps=batch_maps[i, :, :, :], landmarks=batch_landmarks[i, :, :], image_size=image_size, |
|
num_landmarks=num_landmarks) |
|
|
|
|
|
def normalize_map(map_in): |
|
map_min = map_in.min() |
|
return (map_in - map_min) / (map_in.max() - map_min) |
|
|
|
|
|
def map_to_rgb(map_gray): |
|
cmap = plt.get_cmap('jet') |
|
rgba_map_image = cmap(map_gray) |
|
map_rgb = np.delete(rgba_map_image, 3, 2) * 255 |
|
return map_rgb |
|
|
|
|
|
def create_img_with_landmarks(image, landmarks, image_size=256, num_landmarks=68, scale=255, circle_size=2): |
|
"""add landmarks to a face image""" |
|
image = image.reshape(image_size, image_size, -1) |
|
|
|
if scale is 0: |
|
image = 127.5 * (image + 1) |
|
elif scale is 1: |
|
image *= 255 |
|
|
|
landmarks = landmarks.reshape(num_landmarks, 2) |
|
landmarks = np.clip(landmarks, 0, image_size-1) |
|
|
|
for (y, x) in landmarks.astype('int'): |
|
cv2.circle(image, (x, y), circle_size, (255, 0, 0), -1) |
|
|
|
return image |
|
|
|
|
|
def heat_maps_to_image(maps, landmarks=None, image_size=256, num_landmarks=68): |
|
"""create one image from multiple heatmaps""" |
|
|
|
if landmarks is None: |
|
landmarks = heat_maps_to_landmarks(maps, image_size=image_size, num_landmarks=num_landmarks) |
|
|
|
x, y = np.mgrid[0:image_size, 0:image_size] |
|
|
|
pixel_dist = np.sqrt( |
|
np.square(np.expand_dims(x, 2) - landmarks[:, 0]) + np.square(np.expand_dims(y, 2) - landmarks[:, 1])) |
|
|
|
nn_landmark = np.argmin(pixel_dist, 2) |
|
|
|
map_image = maps[x, y, nn_landmark] |
|
map_image = (map_image-map_image.min())/(map_image.max()-map_image.min()) |
|
|
|
return map_image |
|
|
|
|
|
def merge_images_landmarks_maps_gt(images, maps, maps_gt, landmarks=None, image_size=256, num_landmarks=68, |
|
num_samples=9, scale=255, circle_size=2, fast=False): |
|
"""create image for log - containing input face images, predicted heatmaps and GT heatmaps (if exists)""" |
|
|
|
images = images[:num_samples] |
|
if maps.shape[1] is not image_size: |
|
images = zoom(images, (1, 0.25, 0.25, 1)) |
|
image_size /= 4 |
|
image_size=int(image_size) |
|
if maps_gt is not None: |
|
if maps_gt.shape[1] is not image_size: |
|
maps_gt = zoom(maps_gt, (1, 0.25, 0.25, 1)) |
|
|
|
cmap = plt.get_cmap('jet') |
|
|
|
row = int(np.sqrt(num_samples)) |
|
if maps_gt is None: |
|
merged = np.zeros([row * image_size, row * image_size * 2, 3]) |
|
else: |
|
merged = np.zeros([row * image_size, row * image_size * 3, 3]) |
|
|
|
for idx, img in enumerate(images): |
|
i = idx // row |
|
j = idx % row |
|
|
|
if landmarks is None: |
|
img_landmarks = heat_maps_to_landmarks(maps[idx, :, :, :], image_size=image_size, |
|
num_landmarks=num_landmarks) |
|
else: |
|
img_landmarks = landmarks[idx] |
|
|
|
if fast: |
|
map_image = np.amax(maps[idx, :, :, :], 2) |
|
map_image = (map_image - map_image.min()) / (map_image.max() - map_image.min()) |
|
else: |
|
map_image = heat_maps_to_image(maps[idx, :, :, :], img_landmarks, image_size=image_size, |
|
num_landmarks=num_landmarks) |
|
rgba_map_image = cmap(map_image) |
|
map_image = np.delete(rgba_map_image, 3, 2) * 255 |
|
|
|
img = create_img_with_landmarks(img, img_landmarks, image_size, num_landmarks, scale=scale, |
|
circle_size=circle_size) |
|
|
|
if maps_gt is not None: |
|
if fast: |
|
map_gt_image = np.amax(maps_gt[idx, :, :, :], 2) |
|
map_gt_image = (map_gt_image - map_gt_image.min()) / (map_gt_image.max() - map_gt_image.min()) |
|
else: |
|
map_gt_image = heat_maps_to_image(maps_gt[idx, :, :, :], image_size=image_size, |
|
num_landmarks=num_landmarks) |
|
rgba_map_gt_image = cmap(map_gt_image) |
|
map_gt_image = np.delete(rgba_map_gt_image, 3, 2) * 255 |
|
|
|
merged[i * image_size:(i + 1) * image_size, (j * 3) * image_size:(j * 3 + 1) * image_size, :] = img |
|
merged[i * image_size:(i + 1) * image_size, (j * 3 + 1) * image_size:(j * 3 + 2) * image_size, |
|
:] = map_image |
|
merged[i * image_size:(i + 1) * image_size, (j * 3 + 2) * image_size:(j * 3 + 3) * image_size, |
|
:] = map_gt_image |
|
else: |
|
merged[i * image_size:(i + 1) * image_size, (j * 2) * image_size:(j * 2 + 1) * image_size, :] = img |
|
merged[i * image_size:(i + 1) * image_size, (j * 2 + 1) * image_size:(j * 2 + 2) * image_size,:] = map_image |
|
|
|
return merged |
|
|
|
|
|
def map_comapre_channels(images, maps1, maps2, image_size=64, num_landmarks=68, scale=255): |
|
"""create image for log - present one face image, along with all its heatmaps (one for each landmark)""" |
|
|
|
map1 = maps1[0] |
|
if maps2 is not None: |
|
map2 = maps2[0] |
|
image = images[0] |
|
|
|
if image.shape[0] is not image_size: |
|
image = zoom(image, (0.25, 0.25, 1)) |
|
if scale is 1: |
|
image *= 255 |
|
elif scale is 0: |
|
image = 127.5 * (image + 1) |
|
|
|
row = np.ceil(np.sqrt(num_landmarks)).astype(np.int64) |
|
if maps2 is not None: |
|
merged = np.zeros([row * image_size, row * image_size * 2, 3]) |
|
else: |
|
merged = np.zeros([row * image_size, row * image_size, 3]) |
|
|
|
for idx in range(num_landmarks): |
|
i = idx // row |
|
j = idx % row |
|
channel_map = map_to_rgb(normalize_map(map1[:, :, idx])) |
|
if maps2 is not None: |
|
channel_map2 = map_to_rgb(normalize_map(map2[:, :, idx])) |
|
merged[i * image_size:(i + 1) * image_size, (j * 2) * image_size:(j * 2 + 1) * image_size, :] =\ |
|
channel_map |
|
merged[i * image_size:(i + 1) * image_size, (j * 2 + 1) * image_size:(j * 2 + 2) * image_size, :] =\ |
|
channel_map2 |
|
else: |
|
merged[i * image_size:(i + 1) * image_size, j * image_size:(j + 1) * image_size, :] = channel_map |
|
|
|
i = (idx + 1) // row |
|
j = (idx + 1) % row |
|
if maps2 is not None: |
|
merged[i * image_size:(i + 1) * image_size, (j * 2) * image_size:(j * 2 + 1) * image_size, :] = image |
|
else: |
|
merged[i * image_size:(i + 1) * image_size, j * image_size:(j + 1) * image_size, :] = image |
|
return merged |
|
|
|
|