pytorch
198 строк · 7.8 Кб
1
2
3
4
5
6try:7import cv28except ImportError:9pass # skip if opencv is not available10import numpy as np11
12
13# === copied from utils/keypoints.py as reference ===
14_NUM_KEYPOINTS = -1 # cfg.KRCNN.NUM_KEYPOINTS15_INFERENCE_MIN_SIZE = 0 # cfg.KRCNN.INFERENCE_MIN_SIZE16
17
18def heatmaps_to_keypoints(maps, rois):19"""Extracts predicted keypoint locations from heatmaps. Output has shape20(#rois, 4, #keypoints) with the 4 rows corresponding to (x, y, logit, prob)
21for each keypoint.
22"""
23# This function converts a discrete image coordinate in a HEATMAP_SIZE x24# HEATMAP_SIZE image to a continuous keypoint coordinate. We maintain25# consistency with keypoints_to_heatmap_labels by using the conversion from26# Heckbert 1990: c = d + 0.5, where d is a discrete coordinate and c is a27# continuous coordinate.28offset_x = rois[:, 0]29offset_y = rois[:, 1]30
31widths = rois[:, 2] - rois[:, 0]32heights = rois[:, 3] - rois[:, 1]33widths = np.maximum(widths, 1)34heights = np.maximum(heights, 1)35widths_ceil = np.ceil(widths).astype(int)36heights_ceil = np.ceil(heights).astype(int)37
38num_keypoints = np.maximum(maps.shape[1], _NUM_KEYPOINTS)39
40# NCHW to NHWC for use with OpenCV41maps = np.transpose(maps, [0, 2, 3, 1])42min_size = _INFERENCE_MIN_SIZE43
44xy_preds = np.zeros(45(len(rois), 4, num_keypoints), dtype=np.float32)46for i in range(len(rois)):47if min_size > 0:48roi_map_width = int(np.maximum(widths_ceil[i], min_size))49roi_map_height = int(np.maximum(heights_ceil[i], min_size))50else:51roi_map_width = widths_ceil[i]52roi_map_height = heights_ceil[i]53width_correction = widths[i] / roi_map_width54height_correction = heights[i] / roi_map_height55roi_map = cv2.resize(56maps[i], (roi_map_width, roi_map_height),57interpolation=cv2.INTER_CUBIC)58
59# Bring back to CHW60roi_map = np.transpose(roi_map, [2, 0, 1])61roi_map_probs = scores_to_probs(roi_map.copy())62w = roi_map.shape[2]63for k in range(num_keypoints):64pos = roi_map[k, :, :].argmax()65x_int = pos % w66y_int = (pos - x_int) // w67assert (roi_map_probs[k, y_int, x_int] ==68roi_map_probs[k, :, :].max())69x = (x_int + 0.5) * width_correction70y = (y_int + 0.5) * height_correction71xy_preds[i, 0, k] = x + offset_x[i]72xy_preds[i, 1, k] = y + offset_y[i]73xy_preds[i, 2, k] = roi_map[k, y_int, x_int]74xy_preds[i, 3, k] = roi_map_probs[k, y_int, x_int]75
76return xy_preds77
78
79def scores_to_probs(scores):80"""Transforms CxHxW of scores to probabilities spatially."""81channels = scores.shape[0]82for c in range(channels):83temp = scores[c, :, :]84max_score = temp.max()85temp = np.exp(temp - max_score) / np.sum(np.exp(temp - max_score))86scores[c, :, :] = temp87return scores88
89
90def approx_heatmap_keypoint(heatmaps_in, bboxes_in):91'''92Mask R-CNN uses bicubic upscaling before taking the maximum of the heat map
93for keypoints. We are using bilinear upscaling, which means we can approximate
94the maximum coordinate with the low dimension maximum coordinates. We would like
95to avoid bicubic upscaling, because it is computationally expensive. Brown and
96Lowe (Invariant Features from Interest Point Groups, 2002) uses a method for
97fitting a 3D quadratic function to the local sample points to determine the
98interpolated location of the maximum of scale space, and his experiments showed
99that this provides a substantial improvement to matching and stability for
100keypoint extraction. This approach uses the Taylor expansion (up to the
101quadratic terms) of the scale-space function. It is equivalent with the Newton
102method. This efficient method were used in many keypoint estimation algorithms
103like SIFT, SURF etc...
104
105The implementation of Newton methods with numerical analysis is straight forward
106and super simple, though we need a linear solver.
107
108'''
109assert len(bboxes_in.shape) == 2110N = bboxes_in.shape[0]111assert bboxes_in.shape[1] == 4112assert len(heatmaps_in.shape) == 4113assert heatmaps_in.shape[0] == N114keypoint_count = heatmaps_in.shape[1]115heatmap_size = heatmaps_in.shape[2]116assert heatmap_size >= 2117assert heatmaps_in.shape[3] == heatmap_size118
119keypoints_out = np.zeros((N, keypoint_count, 4))120
121for k in range(N):122x0, y0, x1, y1 = bboxes_in[k, :]123xLen = np.maximum(x1 - x0, 1)124yLen = np.maximum(y1 - y0, 1)125softmax_map = scores_to_probs(heatmaps_in[k, :, :, :].copy())126f = heatmaps_in[k]127for j in range(keypoint_count):128f = heatmaps_in[k][j]129maxX = -1130maxY = -1131maxScore = -100.0132maxProb = -100.0133for y in range(heatmap_size):134for x in range(heatmap_size):135score = f[y, x]136prob = softmax_map[j, y, x]137if maxX < 0 or maxScore < score:138maxScore = score139maxProb = prob140maxX = x141maxY = y142
143# print(maxScore, maxX, maxY)144# initialize fmax values of 3x3 grid145# when 3x3 grid going out-of-bound, mirrowing around center146fmax = [[0] * 3 for r in range(3)]147for x in range(3):148for y in range(3):149hm_x = x + maxX - 1150hm_y = y + maxY - 1151hm_x = hm_x - 2 * (hm_x >= heatmap_size) + 2 * (hm_x < 0)152hm_y = hm_y - 2 * (hm_y >= heatmap_size) + 2 * (hm_y < 0)153assert((hm_x < heatmap_size) and (hm_x >= 0))154assert((hm_y < heatmap_size) and (hm_y >= 0))155fmax[y][x] = f[hm_y][hm_x]156
157# print("python fmax ", fmax)158# b = -f'(0), A = f''(0) Hessian matrix159b = [-(fmax[1][2] - fmax[1][0]) / 2, -160(fmax[2][1] - fmax[0][1]) / 2]161A = [[fmax[1][0] - 2 * fmax[1][1] + fmax[1][2],162(fmax[2][2] - fmax[2][0] - fmax[0][2] + fmax[0][0]) / 4],163[(fmax[2][2] - fmax[2][0] - fmax[0][2] + fmax[0][0]) / 4,164fmax[0][1] - 2 * fmax[1][1] + fmax[2][1]]]165# print("python A")166# print(A)167# solve Ax=b168div = A[1][1] * A[0][0] - A[0][1] * A[1][0]169if abs(div) < 0.0001:170deltaX = 0171deltaY = 0172deltaScore = maxScore173else:174deltaY = (b[1] * A[0][0] - b[0] * A[1][0]) / div175deltaX = (b[0] * A[1][1] - b[1] * A[0][1]) / div176# clip delta if going out-of-range of 3x3 grid177if abs(deltaX) > 1.5 or abs(deltaY) > 1.5:178scale = 1.5 / max(abs(deltaX), abs(deltaY))179deltaX *= scale180deltaY *= scale181# score = f(0) + f'(0)*x + 1/2 * f''(0) * x^2182# = f(0) - b*x + 1/2*x*A*x183deltaScore = (184fmax[1][1] - (b[0] * deltaX + b[1] * deltaY) +1850.5 * (deltaX * deltaX * A[0][0] +186deltaX * deltaY * A[1][0] +187deltaY * deltaX * A[0][1] +188deltaY * deltaY * A[1][1]))189
190assert abs(deltaX) <= 1.5191assert abs(deltaY) <= 1.5192
193# final coordinates194keypoints_out[k, j, :] = (195x0 + (maxX + deltaX + .5) * xLen / heatmap_size,196y0 + (maxY + deltaY + .5) * yLen / heatmap_size,197deltaScore,198maxProb,199)200
201keypoints_out = np.transpose(keypoints_out, [0, 2, 1])202
203return keypoints_out204