原文 - https://www.aiuai.cn/aifarm449.html - AIUAI
关键点估计 - 人体关键点(姿态估计) 和服饰关键点(FashionAI/DeepFashion).
单人关键点估计,评测.
关键点正确估计的比例
计算检测的关键点与其对应的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
% 计算 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
检测到的关键点比例.
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