337 lines
12 KiB
Mathematica
337 lines
12 KiB
Mathematica
|
function Create_data_66()
|
||
|
|
||
|
load '../models/pdm/pdm_66_multi_pie';
|
||
|
load '../models/tri_66.mat';
|
||
|
|
||
|
% This script uses the same format used for patch expert training, and
|
||
|
% expects the data to be there
|
||
|
dataset_loc = '../../../CCNF experiments/clnf/patch training/data_preparation/prepared_data/';
|
||
|
addpath('../PDM_helpers/');
|
||
|
|
||
|
scale = '0.5';
|
||
|
prefix= 'combined_';
|
||
|
|
||
|
% Find the available positive training data
|
||
|
data_files = dir(sprintf('%s/%s%s*.mat', dataset_loc, prefix, scale));
|
||
|
centres_all = [];
|
||
|
for i=1:numel(data_files)
|
||
|
|
||
|
% Load the orientation of the training data
|
||
|
load([dataset_loc, '/', data_files(i).name], 'centres');
|
||
|
centres_all = cat(1, centres_all, centres);
|
||
|
|
||
|
end
|
||
|
|
||
|
label_inds = [1:60,62:64,66:68];
|
||
|
|
||
|
% Construct mirror indices (which views need to be flipped to create other
|
||
|
% profile training data)
|
||
|
mirror_inds = zeros(size(centres_all,1), 1);
|
||
|
for i=1:numel(data_files)
|
||
|
|
||
|
% mirrored image has inverse yaw
|
||
|
mirrored_centre = centres_all(i,:);
|
||
|
mirrored_centre(2) = -mirrored_centre(2);
|
||
|
|
||
|
% if mirrored version has same orientation, do not need mirroring
|
||
|
if(~isequal(mirrored_centre, centres_all(i,:)))
|
||
|
|
||
|
centres_all = cat(1, centres_all, mirrored_centre);
|
||
|
mirror_inds = cat(1, mirror_inds, i);
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
outputLocation = './prep_data/';
|
||
|
|
||
|
num_more_neg = 10;
|
||
|
|
||
|
% Make sure same data generated all the time
|
||
|
rng(0);
|
||
|
|
||
|
neg_image_loc = './neg/';
|
||
|
|
||
|
neg_images = cat(1,dir([neg_image_loc, '/*.jpg']),dir([neg_image_loc, '/*.png']));
|
||
|
|
||
|
max_img_used = 1500;
|
||
|
|
||
|
%% do it separately for centers due to memory limitations
|
||
|
for r=1:size(centres_all,1)
|
||
|
|
||
|
a_mod = 0.3;
|
||
|
|
||
|
mirror = false;
|
||
|
|
||
|
if(mirror_inds(r) ~= 0 )
|
||
|
mirror = true;
|
||
|
label_mirror_inds = [1,17;2,16;3,15;4,14;5,13;6,12;7,11;8,10;18,27;19,26;20,25;21,24;22,23;...
|
||
|
32,36;33,35;37,46;38,45;39,44;40,43;41,48;42,47;49,55;50,54;51,53;60,56;59,57;...
|
||
|
61,63;66,64];
|
||
|
load([dataset_loc, '/', data_files(mirror_inds(r)).name]);
|
||
|
else
|
||
|
load([dataset_loc, '/', data_files(r).name]);
|
||
|
end
|
||
|
|
||
|
% Convert to 66 point model
|
||
|
landmark_locations = landmark_locations(:,label_inds,:);
|
||
|
|
||
|
visiCurrent = logical(visiIndex);
|
||
|
|
||
|
% Flip the orientation and indices for mirror data
|
||
|
if(mirror)
|
||
|
centres = [centres(1), -centres(2), -centres(3)];
|
||
|
tmp1 = visiCurrent(label_mirror_inds(:,1));
|
||
|
tmp2 = visiCurrent(label_mirror_inds(:,2));
|
||
|
visiCurrent(label_mirror_inds(:,2)) = tmp1;
|
||
|
visiCurrent(label_mirror_inds(:,1)) = tmp2;
|
||
|
end
|
||
|
|
||
|
visibleVerts = 1:numel(visiCurrent);
|
||
|
visibleVerts = visibleVerts(visiCurrent)-1;
|
||
|
|
||
|
% Correct the triangulation to take into account the vertex
|
||
|
% visibilities
|
||
|
triangulation = [];
|
||
|
|
||
|
shape = a_mod * Euler2Rot(centres * pi/180) * reshape(M, numel(M)/3, 3)';
|
||
|
shape = shape';
|
||
|
|
||
|
for i=1:size(T,1)
|
||
|
visib = 0;
|
||
|
for j=1:numel(visibleVerts)
|
||
|
if(T(i,1)==visibleVerts(j))
|
||
|
visib = visib+1;
|
||
|
end
|
||
|
if(T(i,2)==visibleVerts(j))
|
||
|
visib = visib+1;
|
||
|
end
|
||
|
if(T(i,3)==visibleVerts(j))
|
||
|
visib = visib+1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
% Only if all three of the vertices are visible
|
||
|
if(visib == 3)
|
||
|
|
||
|
% Also want to remove triangles facing the wrong way (self occluded)
|
||
|
v1 = [shape(T(i,1)+1,1), shape(T(i,1)+1,2), shape(T(i,1)+1,3)];
|
||
|
v2 = [shape(T(i,2)+1,1), shape(T(i,2)+1,2), shape(T(i,2)+1,3)];
|
||
|
v3 = [shape(T(i,3)+1,1), shape(T(i,3)+1,2), shape(T(i,3)+1,3)];
|
||
|
normal = cross((v2-v1), v3 - v2);
|
||
|
normal = normal / norm(normal);
|
||
|
direction = normal * [0,0,1]';
|
||
|
|
||
|
% And only if the triangle is facing the camera
|
||
|
if(direction > 0)
|
||
|
triangulation = cat(1, triangulation, T(i,:));
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
% Initialise the warp
|
||
|
[ alphas, betas, triX, mask, minX, minY, nPix ] = InitialisePieceWiseAffine(triangulation, shape);
|
||
|
|
||
|
imgs_to_use = randperm(size(landmark_locations, 1));
|
||
|
|
||
|
if(size(landmark_locations, 1) > max_img_used)
|
||
|
imgs_to_use = imgs_to_use(1:max_img_used);
|
||
|
end
|
||
|
|
||
|
% Extracting relevant filenames
|
||
|
examples = zeros(numel(imgs_to_use) * (num_more_neg+1), nPix);
|
||
|
errors = zeros(numel(imgs_to_use) * (num_more_neg+1), 1);
|
||
|
|
||
|
unused_pos = 0;
|
||
|
|
||
|
curr_filled = 0;
|
||
|
|
||
|
for j=imgs_to_use
|
||
|
|
||
|
labels = squeeze(landmark_locations(j,:,:));
|
||
|
|
||
|
img = squeeze(all_images(j,:,:));
|
||
|
|
||
|
if(mirror)
|
||
|
img = fliplr(img);
|
||
|
imgSize = size(img);
|
||
|
flippedLbls = labels;
|
||
|
flippedLbls(:,1) = imgSize(1) - flippedLbls(:,1);
|
||
|
tmp1 = flippedLbls(label_mirror_inds(:,1),:);
|
||
|
tmp2 = flippedLbls(label_mirror_inds(:,2),:);
|
||
|
flippedLbls(label_mirror_inds(:,2),:) = tmp1;
|
||
|
flippedLbls(label_mirror_inds(:,1),:) = tmp2;
|
||
|
labels = flippedLbls;
|
||
|
end
|
||
|
|
||
|
% If for some reason some of the labels are not visible in the
|
||
|
% current sample skip this label
|
||
|
non_existent_labels = labels(:,1)==0 | labels(:,2)==0;
|
||
|
non_existent_inds = find(non_existent_labels)-1;
|
||
|
if(numel(intersect(triangulation(:), non_existent_inds)) > 0)
|
||
|
unused_pos = unused_pos + 1;
|
||
|
continue;
|
||
|
end
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
[features] = ExtractFaceFeatures(img, labels, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
% Extract the correct PDM parameters for the model (we will perturb
|
||
|
% them for some negative examples)
|
||
|
[ a_orig, R_orig, trans_orig, ~, params_orig] = fit_PDM_ortho_proj_to_2D(M, E, V, labels);
|
||
|
eul_orig = Rot2Euler(R_orig);
|
||
|
|
||
|
% a slightly perturbed example, too tight
|
||
|
% from 0.3 to 0.9
|
||
|
a_mod = a_orig * (0.6 + (randi(7) - 4)*0.1);
|
||
|
p_global = [a_mod; eul_orig'; trans_orig];
|
||
|
|
||
|
labels_mod = GetShapeOrtho(M, V, params_orig, p_global);
|
||
|
labels_mod = labels_mod(:,1:2);
|
||
|
|
||
|
[features] = ExtractFaceFeatures(img, labels_mod, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
% Compute the badness of fit
|
||
|
error = norm(labels_mod(:) - labels(:)) / (max(labels(:,2))-min(labels(:,2)));
|
||
|
errors(curr_filled,:) = error;
|
||
|
|
||
|
% a slightly perturbed example, too broad
|
||
|
% from 1.2 to 0.6
|
||
|
a_mod = a_orig * (1.4 + (randi(5) - 3)*0.1);
|
||
|
p_global = [a_mod; eul_orig'; trans_orig];
|
||
|
|
||
|
labels_mod = GetShapeOrtho(M, V, params_orig, p_global);
|
||
|
labels_mod = labels_mod(:,1:2);
|
||
|
|
||
|
[features] = ExtractFaceFeatures(img, labels_mod, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
error = norm(labels_mod(:) - labels(:)) / (max(labels(:,2))-min(labels(:,2)));
|
||
|
errors(curr_filled,:) = error;
|
||
|
|
||
|
% A somewhat offset example
|
||
|
|
||
|
trans_mod = trans_orig + randn(2,1) * 10;
|
||
|
p_global = [a_orig; eul_orig'; trans_mod];
|
||
|
|
||
|
labels_mod = GetShapeOrtho(M, V, params_orig, p_global);
|
||
|
labels_mod = labels_mod(:,1:2);
|
||
|
|
||
|
[features] = ExtractFaceFeatures(img, labels_mod, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
error = norm(labels_mod(:) - labels(:)) / (max(labels(:,2))-min(labels(:,2)));
|
||
|
errors(curr_filled,:) = error;
|
||
|
|
||
|
% A rotated sample
|
||
|
eul_mod = eul_orig + randn(1,3)*0.2;
|
||
|
p_global = [a_orig; eul_mod'; trans_orig];
|
||
|
|
||
|
labels_mod = GetShapeOrtho(M, V, params_orig, p_global);
|
||
|
labels_mod = labels_mod(:,1:2);
|
||
|
|
||
|
[features] = ExtractFaceFeatures(img, labels_mod, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
error = norm(labels_mod(:) - labels(:)) / (max(labels(:,2))-min(labels(:,2)));
|
||
|
errors(curr_filled,:) = error;
|
||
|
|
||
|
% A sample with modified shape parameters
|
||
|
p_global = [a_orig; eul_orig'; trans_orig];
|
||
|
params_mod = params_orig + randn(size(params_orig)).*sqrt(E);
|
||
|
labels_mod = GetShapeOrtho(M, V, params_mod, p_global);
|
||
|
labels_mod = labels_mod(:,1:2);
|
||
|
|
||
|
[features] = ExtractFaceFeatures(img, labels_mod, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
error = norm(labels_mod(:) - labels(:)) / (max(labels(:,2))-min(labels(:,2)));
|
||
|
errors(curr_filled,:) = error;
|
||
|
|
||
|
% pick a random image from negative inriaperson dataset, use original location if
|
||
|
% first, otherwhise resize it to fit
|
||
|
for n=6:num_more_neg
|
||
|
n_img = randi(numel(neg_images));
|
||
|
|
||
|
neg_image = imread([neg_image_loc, neg_images(n_img).name]);
|
||
|
|
||
|
if(size(neg_image,3) == 3)
|
||
|
neg_image = rgb2gray(neg_image);
|
||
|
end
|
||
|
|
||
|
[h_neg, w_neg] = size(neg_image);
|
||
|
|
||
|
% if the current labels fit just use them, if not, then resize
|
||
|
% to fit
|
||
|
max_x = max(labels(:,1));
|
||
|
max_y = max(labels(:,2));
|
||
|
|
||
|
if(max_x > w_neg || max_y > h_neg)
|
||
|
neg_image = imresize(neg_image, [max_y, max_x]);
|
||
|
end
|
||
|
|
||
|
[features] = ExtractFaceFeatures(neg_image, labels, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
|
||
|
curr_filled = curr_filled + 1;
|
||
|
examples(curr_filled,:) = features;
|
||
|
|
||
|
% Set high error to 3
|
||
|
errors(curr_filled,:) = 3;
|
||
|
end
|
||
|
|
||
|
|
||
|
if(mod(curr_filled, 10) == 0)
|
||
|
fprintf('%d/%d done\n', curr_filled/(num_more_neg+1), numel(imgs_to_use));
|
||
|
end
|
||
|
% add the pos example to the background
|
||
|
|
||
|
end
|
||
|
|
||
|
examples = examples(1:curr_filled,:);
|
||
|
errors = errors(1:curr_filled);
|
||
|
|
||
|
% svm training
|
||
|
filename = sprintf('%s/face_checker_general_training_66_%d.mat', outputLocation, r);
|
||
|
save(filename, 'examples', 'errors', 'alphas', 'betas', 'triangulation', 'minX', 'minY', 'nPix', 'shape', 'triX', 'mask', 'centres');
|
||
|
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
function [features] = ExtractFaceFeatures(img, labels, triangulation, triX, mask, alphas, betas, nPix, minX, minY)
|
||
|
|
||
|
% Make sure labels are within range
|
||
|
[hRes, wRes] = size(img);
|
||
|
labels(labels(:,1) < 1,1) = 1;
|
||
|
labels(labels(:,2) < 1,2) = 1;
|
||
|
|
||
|
labels(labels(:,1) > wRes-1,1) = wRes-1;
|
||
|
labels(labels(:,2) > hRes-1,2) = hRes-1;
|
||
|
|
||
|
crop_img = Crop(img, labels, triangulation, triX, mask, alphas, betas, nPix, minX, minY);
|
||
|
crop_img(isnan(crop_img)) = 0;
|
||
|
|
||
|
% vectorised version
|
||
|
features = reshape(crop_img(logical(mask)), 1, nPix);
|
||
|
|
||
|
% normalisations
|
||
|
features = (features - mean(features));
|
||
|
norms = std(features);
|
||
|
if(norms==0)
|
||
|
norms = 1;
|
||
|
end
|
||
|
features = features / norms;
|
||
|
end
|