text: # ------------------------------------------------------------------------------
  # Copyright (c) Microsoft
  # Licensed under the MIT License.
  # Written by Bin Xiao (Bin.Xiao@microsoft.com)
  # ------------------------------------------------------------------------------
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import numpy as np
  
  from lib.core.inference import get_max_preds
  
  def calc_dists(preds, target, normalize):
      preds = preds.astype(np.float32)
      target = target.astype(np.float32)
      dists = np.zeros((preds.shape[1], preds.shape[0]))
      for n in range(preds.shape[0]):
          for c in range(preds.shape[1]):
              if target[n, c, 0] > 1 and target[n, c, 1] > 1:
                  normed_preds = preds[n, c, :] / normalize[n]
                  normed_targets = target[n, c, :] / normalize[n]
                  dists[c, n] = np.linalg.norm(normed_preds - normed_targets)
              else:
                  dists[c, n] = -1
      return dists
  
  
  def dist_acc(dists, thr=0.5):
      ''' Return percentage below threshold while ignoring values with a -1 '''
      dist_cal = np.not_equal(dists, -1)
      num_dist_cal = dist_cal.sum()
      if num_dist_cal > 0:
          return np.less(dists[dist_cal], thr).sum() * 1.0 / num_dist_cal
      else:
          return -1
  
  
  def accuracy(output, target, hm_type='gaussian', thr=0.5):
      '''
      Calculate accuracy according to PCK,
      but uses ground truth heatmap rather than x,y locations
      First value to be returned is average accuracy across 'idxs',
      followed by individual accuracies
      '''
      idx = list(range(output.shape[1]))
      norm = 1.0
      if hm_type == 'gaussian':
          pred, _ = get_max_preds(output)
          target, _ = get_max_preds(target)
          h = output.shape[2]
          w = output.shape[3]
          norm = np.ones((pred.shape[0], 2)) * np.array([h, w]) / 10
      dists = calc_dists(pred, target, norm)
  
      acc = np.zeros((len(idx) + 1))
      avg_acc = 0
      cnt = 0
  
      for i in range(len(idx)):
          acc[i + 1] = dist_acc(dists[idx[i]])
          if acc[i + 1] >= 0:
              avg_acc = avg_acc + acc[i + 1]
              cnt += 1
  
      avg_acc = avg_acc / cnt if cnt != 0 else 0
      if cnt != 0:
          acc[0] = avg_acc
      return acc, avg_acc, cnt, pred
  