关键点估计 - 人体关键点(姿态估计) 和服饰关键点(FashionAI/DeepFashion).
单人关键点估计,评测.

1. PCK - Percentage of Correct Keypoints

关键点正确估计的比例
计算检测的关键点与其对应的groundtruth间的归一化距离小于设定阈值的比例(the percentage of detections that fall within a normalized distance of the ground truth).

FLIC 中是以躯干直径(torso size) 作为归一化参考.
MPII 中是以头部长度(head length) 作为归一化参考,即 PCKh.
function eval_pck(pred, joints, symmetry_joint_id, joint_name, name)
% PCK 的实现
% torso height: || left_shoulder - right hip ||
% symmetry_joint_id: 具有对称关系的关键点 ID
% joint_name: 具有对称关系的关键点名字

range = 0:0.01:0.1;
show_joint_ids = (symmetry_joint_id >= 1:numel(symmetry_joint_id));

% compute distance to ground truth joints
dist = get_dist_pck(pred, joints(1:2,:,:));

% 计算 PCK
pck_all = compute_pck(dist,range);
pck = pck_all(end, :);
pck(1:end-1) = (pck(1:end-1) + pck(symmetry_joint_id))/2;

% 可视化结果
pck = [pck(show_joint_ids) pck(end)];
fprintf('------------ PCK Evaluation: %s -------------\n', name);
fprintf('Parts '); fprintf('& %s ', joint_name{:}); fprintf('& Mean\n');
fprintf('PCK   '); fprintf('& %.1f  ', pck); fprintf('\n');

% -------------------------------------------------------------------------
function dist = get_dist_pck(pred, gt)
assert(size(pred,1) == size(gt,1) && size(pred,2) == size(gt,2) && size(pred,3) == size(gt,3));

dist = nan(1,size(pred, 2), size(pred,3));

for imgidx = 1:size(pred,3)
  % torso diameter 躯干直径
  if size(gt, 2) == 14
    refDist = norm(gt(:,10,imgidx) - gt(:,3,imgidx));
  elseif size(gt, 2) == 10 % 10 joints FLIC
    refDist = norm(gt(:,7,imgidx) - gt(:,6,imgidx));
  elseif size(gt, 2) == 11 % 11 joints FLIC
    refDist = norm(gt(:,4,imgidx) - gt(:,11,imgidx));
  else
    error('Number of joints should be 14 or 10 or 11');
  end

  % 预测的关键点与 gt 关键点的距离
  dist(1,:,imgidx) = sqrt(sum((pred(:,:,imgidx) - gt(:,:,imgidx)).^2,1))./refDist;

end

% -------------------------------------------------------------------------
function pck = compute_pck(dist,range)
pck = zeros(numel(range),size(dist,2)+1);

for jidx = 1:size(dist,2)
  % 计算每个设定阈值的 PCK
  for k = 1:numel(range)
    pck(k,jidx) = 100*mean(squeeze(dist(1,jidx,:)) <= range(k));
  end
end

% 计算平均 PCK
for k = 1:numel(range)
  pck(k,end) = 100*mean(reshape(squeeze(dist(1,:,:)),size(dist,2)*size(dist,3),1) <= range(k));
end

输出结果如下:

------------ PCK Evaluation: Single_People -------------
Parts & Ankle & Knee & Hip & Wris & Elbo & Shou & Head & Mean
PCK   & 93.2  & 88.3  & 70.4  & 92.1  & 92.6  & 94.6  & 95.9  & 89.6

1.1 PCKh

% 计算 head 的长度
headSize = getHeadSizeAll(annolist_test_flat(single_person_test_flat == 1));

% 计算预测的关键点与 gt 关键点间的归一化距离
dist = getDistPCKh(pred,gt,headSize);

% 计算 PCKh
pck = computePCK(dist,range);


function headSizeAll = getHeadSizeAll(annolist)
headSizeAll = nan(length(annolist),1);
for imgidx = 1:length(annolist)
    rect = annolist(imgidx).annorect;
    headSizeAll(imgidx) =  util_get_head_size(rect);
end
end

function headSize = util_get_head_size(rect)
SC_BIAS = 0.6; % 0.8*0.75
headSize = SC_BIAS*norm([rect.x2 rect.y2] - [rect.x1 rect.y1]); # head 的两个点间的距离
end

function dist = getDistPCKh(pred,gt,refDist)
assert(size(pred,1) == size(gt,1) && size(pred,2) == size(gt,2) && size(pred,3) == size(gt,3));
assert(size(refDist,1) == size(gt,3));

dist = nan(1,size(pred,2),size(pred,3));
for imgidx = 1:size(pred,3)
    % pred joints 与 gt joints 的归一化距离
    dist(1,:,imgidx) = sqrt(sum((pred(:,:,imgidx) - gt(:,:,imgidx)).^2,1))./refDist(imgidx);
end

function pck = computePCK(dist,range)
pck = zeros(numel(range),size(dist,2)+2);
for jidx = 1:size(dist,2)
    % 计算各阈值的 PCK
    for k = 1:numel(range)
        d = squeeze(dist(1,jidx,:));
        % dist is NaN if gt is missing; ignore dist in this case
        pck(k,jidx) = 100*mean(d(~isnan(d))<=range(k));
    end
end

% 计算上半身关键点的平均 PCK
for k = 1:numel(range)
    d = reshape(squeeze(dist(1,7:12,:)),6*size(dist,3),1);
    pck(k,end-1) = 100*mean(d(~isnan(d))<=range(k));
end

% 计算全身关键点的 PCK
for k = 1:numel(range)
    d = reshape(squeeze(dist(1,:,:)),size(dist,2)*size(dist,3),1);
    pck(k,end) = 100*mean(d(~isnan(d))<=range(k));
end
end

2. PDJ - Percentage of Detected Joints

检测到的关键点比例.

function [accs, range] = eval_pdj(pred, joints, reference_joints_pair, symmetry_joint_id, joint_name, eval_name)
% 设定选定的参考点:reference_joints_pair = [3, 10];     % 右肩点到左臀点
% symmetry_joint_id: 具有对称关系的关键点 ID
assert(numel(reference_joints_pair) == 2);
show_joint_ids = find(symmetry_joint_id >= 1:numel(symmetry_joint_id)); 
range = 0:0.01:0.5;

num = size(pred, 3);
assert(num >= 1);
% the number of joints
joint_n = size(joints, 2);

scale = zeros(1, num);
for ii = 1:num
  scale(ii) = norm( joints(:,reference_joints_pair(1), ii) - joints(:,reference_joints_pair(2), ii) );
  %scale(ii) = 100;
end

dists = zeros(num, joint_n);
for ii = 1:num
  dists(ii,:) = sqrt(sum( (pred(:, :, ii) - joints(:,:,ii)).^2, 1 ));
  dists(ii,:) = dists(ii,:) / scale(ii);
end

accs = zeros(numel(range), joint_n);
for ii = 1:numel(range)
  accs(ii,:) = mean(dists <= range(ii),1);
end

accs = (accs + accs(:,symmetry_joint_id)) / 2;
accs = accs(:, show_joint_ids);
% print
fprintf('-------------- PDJ Evaluation ---------------\n')
fprintf('Joints    '); fprintf('& %s ', joint_name{:}); fprintf('\n');
sample_pdj_thresholds = [0.1, 0.2, 0.3, 0.4];
for ii = 1:length(sample_pdj_thresholds)
  t = sample_pdj_thresholds(ii);
  idx = (range == t);
  fprintf('PDJ@%.2f  ', t); fprintf('& %.1f ', accs(idx,:)*100); fprintf('\n');
end

% plot
line_width = 2;
p_color = {'g','y','b','r','c','k','m'};

% visualize
figure; hold on; grid on;
for ii = 1:numel(show_joint_ids)
  plot(range, accs(:, ii), p_color{mod(ii, numel(p_color))+1}, 'linewidth', line_width);
end
leg_str = cell(numel(show_joint_ids), 1);
for ii = 1:numel(show_joint_ids)
  leg_str{ii} = sprintf('%s', joint_name{ii});
end
h_leg = legend(leg_str, 'FontSize', 12);
set(h_leg, 'location', 'southeast', 'linewidth', 1);

axis([range(1),range(end), 0, 1]);
set(gca,'ytick', 0:0.1:1);
set(gca, 'linewidth', 1);

% --- titles
xlabel('Normalized  Threshold') % x-axis label
ylabel('Detection Rate') % y-axis label

title([eval_name ' PDJ']);
hold off;

输出结果为:

-------------- PDJ Evaluation ---------------
Joints    & Ankle & Knee & Hip & Wris & Elbo & Shou & Head 
PDJ@0.10  & 93.3 & 87.6 & 66.4 & 91.8 & 92.6 & 95.5 & 96.1 
PDJ@0.20  & 97.5 & 94.7 & 93.4 & 96.8 & 97.9 & 98.8 & 99.1 
PDJ@0.30  & 97.9 & 95.7 & 97.6 & 97.8 & 98.4 & 99.1 & 99.2 
PDJ@0.40  & 98.1 & 96.1 & 98.4 & 98.1 & 98.6 & 99.2 & 99.2 
Last modification:October 9th, 2018 at 09:31 am