Module deepposekit.utils.keypoints
Expand source code
# -*- coding: utf-8 -*-
# Copyright 2018-2019 Jacob M. Graving <jgraving@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import cv2
import imgaug as ia
MACHINE_EPSILON = np.finfo(np.float64).eps
__all__ = [
"draw_confidence_maps",
"draw_confidence_map",
"graph_to_edges",
"draw_keypoints",
"draw_graph",
"numpy_to_imgaug",
"imgaug_to_numpy",
"keypoint_errors",
]
def graph_to_edges(graph):
edges = graph.copy()
parents = set()
edge = {}
for idx in range(len(edges)):
if edges[idx] == -1:
parents.add(idx)
else:
edge[idx] = edges[idx]
for idx in range(len(edges)):
if idx in parents:
edges[idx] = idx
else:
idx0 = idx
while idx0 not in parents:
idx0 = edge[idx0]
edges[idx] = idx0
return edges
def draw_graph(keypoints, height, width, output_shape, graph, sigma=1, linewidth=1):
# One channel for each edge
keypoints = keypoints.copy()
edge_labels = graph_to_edges(graph)
labels = np.unique(edge_labels)
out_height = output_shape[0]
out_width = output_shape[1]
sigma *= height / out_height
output_shape = (out_height, out_width, labels.shape[0])
confidence = np.zeros(output_shape, dtype=np.float64)
edge_confidence_list = []
for idx, label in enumerate(labels):
lines = graph[edge_labels == label]
lines_idx = np.where(edge_labels == label)[0]
edge_confidence = np.zeros((out_height, out_width, lines.shape[0]))
zeros = np.zeros((height, width, 1), dtype=np.uint8)
for jdx, (line_idx, line) in enumerate(zip(lines_idx, lines)):
if line >= 0:
pt1 = keypoints[line_idx]
pt2 = keypoints[line]
line_map = cv2.line(
zeros.copy(),
(int(pt1[0]), int(pt1[1])),
(int(pt2[0]), int(pt2[1])),
1,
linewidth,
lineType=cv2.LINE_AA,
)
blurred = cv2.GaussianBlur(
line_map.astype(np.float64), (height + 1, width + 1), sigma
)
resized = cv2.resize(blurred, (out_width, out_height)) + MACHINE_EPSILON
edge_confidence[..., jdx] = resized
edge_confidence = edge_confidence[..., 1:]
edge_confidence_list.append(edge_confidence)
confidence[..., idx] = edge_confidence.sum(-1)
edge_confidence = np.concatenate(edge_confidence_list, -1)
confidence = np.concatenate((confidence, edge_confidence), -1)
return confidence
def draw_keypoints(keypoints, height, width, output_shape, sigma=1, normalize=True):
keypoints = keypoints.copy()
n_keypoints = keypoints.shape[0]
out_height = output_shape[0]
out_width = output_shape[1]
keypoints[:, 1] *= out_height / height
keypoints[:, 0] *= out_width / width
confidence = np.zeros((out_height, out_width, n_keypoints))
xv = np.arange(out_width)
yv = np.arange(out_height)
xx, yy = np.meshgrid(xv, yv)
for idx in range(n_keypoints):
keypoint = keypoints[idx]
gaussian = (yy - keypoint[1]) ** 2
gaussian += (xx - keypoint[0]) ** 2
gaussian *= -1
gaussian /= 2 * sigma ** 2
gaussian = np.exp(gaussian)
confidence[..., idx] = gaussian
if not normalize:
confidence /= sigma * np.sqrt(2 * np.pi)
return confidence
def draw_confidence_map(
image, keypoints, graph=None, output_shape=None, use_graph=True, sigma=1
):
height = image.shape[0]
width = image.shape[1]
if not output_shape:
output_shape = image.shape[:2]
keypoints_confidence = draw_keypoints(keypoints, height, width, output_shape, sigma)
if use_graph and isinstance(graph, np.ndarray):
edge_confidence = draw_graph(
keypoints, height, width, output_shape, graph, sigma
)
sum_keypoints = keypoints_confidence.sum(-1, keepdims=True)
idx = np.unique(graph_to_edges(graph)).shape[0]
sum_edges = edge_confidence[..., :idx].sum(-1, keepdims=True)
sum_edges_keypoints = np.concatenate((sum_edges, sum_keypoints), -1)
sum_edges_keypoints = sum_edges_keypoints.sum(-1, keepdims=True)
confidence = (
keypoints_confidence,
edge_confidence,
sum_edges,
sum_edges_keypoints,
)
confidence = np.concatenate(confidence, -1)
else:
confidence = keypoints_confidence
return confidence
def draw_confidence_maps(
images, keypoints, graph=None, output_shape=None, use_graph=True, sigma=1
):
n_samples = keypoints.shape[0]
confidence_maps = []
for idx in range(n_samples):
confidence = draw_confidence_map(
images[idx], keypoints[idx], graph, output_shape, use_graph, sigma
)
confidence_maps.append(confidence)
confidence_maps = np.stack(confidence_maps)
return confidence_maps
def numpy_to_imgaug(image, keypoints):
"""Returns imgaug keypoints"""
keypoints_list = []
for keypoint in keypoints:
keypoints_list.append(ia.Keypoint(x=keypoint[0], y=keypoint[1]))
keypoints = ia.KeypointsOnImage(keypoints_list, shape=image.shape)
return keypoints
def imgaug_to_numpy(keypoints):
"""Returns numpy keypoints"""
keypoints_list = []
for keypoint in keypoints.keypoints:
keypoints_list.append([keypoint.x, keypoint.y])
keypoints = np.stack(keypoints_list)
return keypoints
def keypoint_errors(y_true, y_pred):
y_error = y_true - y_pred
euclidean = np.sqrt(np.sum(y_error ** 2, axis=-1))
mae = np.mean(np.abs(y_error), axis=-1)
mse = np.mean(y_error ** 2, axis=-1)
rmse = np.sqrt(mse)
return [y_error, euclidean, mae, mse, rmse]
Functions
def draw_confidence_map(image, keypoints, graph=None, output_shape=None, use_graph=True, sigma=1)
-
Expand source code
def draw_confidence_map( image, keypoints, graph=None, output_shape=None, use_graph=True, sigma=1 ): height = image.shape[0] width = image.shape[1] if not output_shape: output_shape = image.shape[:2] keypoints_confidence = draw_keypoints(keypoints, height, width, output_shape, sigma) if use_graph and isinstance(graph, np.ndarray): edge_confidence = draw_graph( keypoints, height, width, output_shape, graph, sigma ) sum_keypoints = keypoints_confidence.sum(-1, keepdims=True) idx = np.unique(graph_to_edges(graph)).shape[0] sum_edges = edge_confidence[..., :idx].sum(-1, keepdims=True) sum_edges_keypoints = np.concatenate((sum_edges, sum_keypoints), -1) sum_edges_keypoints = sum_edges_keypoints.sum(-1, keepdims=True) confidence = ( keypoints_confidence, edge_confidence, sum_edges, sum_edges_keypoints, ) confidence = np.concatenate(confidence, -1) else: confidence = keypoints_confidence return confidence
def draw_confidence_maps(images, keypoints, graph=None, output_shape=None, use_graph=True, sigma=1)
-
Expand source code
def draw_confidence_maps( images, keypoints, graph=None, output_shape=None, use_graph=True, sigma=1 ): n_samples = keypoints.shape[0] confidence_maps = [] for idx in range(n_samples): confidence = draw_confidence_map( images[idx], keypoints[idx], graph, output_shape, use_graph, sigma ) confidence_maps.append(confidence) confidence_maps = np.stack(confidence_maps) return confidence_maps
def draw_graph(keypoints, height, width, output_shape, graph, sigma=1, linewidth=1)
-
Expand source code
def draw_graph(keypoints, height, width, output_shape, graph, sigma=1, linewidth=1): # One channel for each edge keypoints = keypoints.copy() edge_labels = graph_to_edges(graph) labels = np.unique(edge_labels) out_height = output_shape[0] out_width = output_shape[1] sigma *= height / out_height output_shape = (out_height, out_width, labels.shape[0]) confidence = np.zeros(output_shape, dtype=np.float64) edge_confidence_list = [] for idx, label in enumerate(labels): lines = graph[edge_labels == label] lines_idx = np.where(edge_labels == label)[0] edge_confidence = np.zeros((out_height, out_width, lines.shape[0])) zeros = np.zeros((height, width, 1), dtype=np.uint8) for jdx, (line_idx, line) in enumerate(zip(lines_idx, lines)): if line >= 0: pt1 = keypoints[line_idx] pt2 = keypoints[line] line_map = cv2.line( zeros.copy(), (int(pt1[0]), int(pt1[1])), (int(pt2[0]), int(pt2[1])), 1, linewidth, lineType=cv2.LINE_AA, ) blurred = cv2.GaussianBlur( line_map.astype(np.float64), (height + 1, width + 1), sigma ) resized = cv2.resize(blurred, (out_width, out_height)) + MACHINE_EPSILON edge_confidence[..., jdx] = resized edge_confidence = edge_confidence[..., 1:] edge_confidence_list.append(edge_confidence) confidence[..., idx] = edge_confidence.sum(-1) edge_confidence = np.concatenate(edge_confidence_list, -1) confidence = np.concatenate((confidence, edge_confidence), -1) return confidence
def draw_keypoints(keypoints, height, width, output_shape, sigma=1, normalize=True)
-
Expand source code
def draw_keypoints(keypoints, height, width, output_shape, sigma=1, normalize=True): keypoints = keypoints.copy() n_keypoints = keypoints.shape[0] out_height = output_shape[0] out_width = output_shape[1] keypoints[:, 1] *= out_height / height keypoints[:, 0] *= out_width / width confidence = np.zeros((out_height, out_width, n_keypoints)) xv = np.arange(out_width) yv = np.arange(out_height) xx, yy = np.meshgrid(xv, yv) for idx in range(n_keypoints): keypoint = keypoints[idx] gaussian = (yy - keypoint[1]) ** 2 gaussian += (xx - keypoint[0]) ** 2 gaussian *= -1 gaussian /= 2 * sigma ** 2 gaussian = np.exp(gaussian) confidence[..., idx] = gaussian if not normalize: confidence /= sigma * np.sqrt(2 * np.pi) return confidence
def graph_to_edges(graph)
-
Expand source code
def graph_to_edges(graph): edges = graph.copy() parents = set() edge = {} for idx in range(len(edges)): if edges[idx] == -1: parents.add(idx) else: edge[idx] = edges[idx] for idx in range(len(edges)): if idx in parents: edges[idx] = idx else: idx0 = idx while idx0 not in parents: idx0 = edge[idx0] edges[idx] = idx0 return edges
def imgaug_to_numpy(keypoints)
-
Returns numpy keypoints
Expand source code
def imgaug_to_numpy(keypoints): """Returns numpy keypoints""" keypoints_list = [] for keypoint in keypoints.keypoints: keypoints_list.append([keypoint.x, keypoint.y]) keypoints = np.stack(keypoints_list) return keypoints
def keypoint_errors(y_true, y_pred)
-
Expand source code
def keypoint_errors(y_true, y_pred): y_error = y_true - y_pred euclidean = np.sqrt(np.sum(y_error ** 2, axis=-1)) mae = np.mean(np.abs(y_error), axis=-1) mse = np.mean(y_error ** 2, axis=-1) rmse = np.sqrt(mse) return [y_error, euclidean, mae, mse, rmse]
def numpy_to_imgaug(image, keypoints)
-
Returns imgaug keypoints
Expand source code
def numpy_to_imgaug(image, keypoints): """Returns imgaug keypoints""" keypoints_list = [] for keypoint in keypoints: keypoints_list.append(ia.Keypoint(x=keypoint[0], y=keypoint[1])) keypoints = ia.KeypointsOnImage(keypoints_list, shape=image.shape) return keypoints