%create_nullspace Create null-space for scene with perspective camera. % % Parameters: % depths .. matrix of zeros and ones meaning whether corresponding element % in M is scaled (i.e. multiplied by known perspective depth) function [nullspace, result] = create_nullspace(M, depths, central, opt) if nargin < 4, opt.trial_coef = 1; opt.threshold = .01; end I = ~isnan(M(1:3:end,:)); [m n] = size(I); show_mod = 10; use_maxtuples = 0; if opt.verbose, fprintf(1, 'Used 4-tuples (.=%d): ', show_mod); tic; end if central, cols_scaled(1:n) = 0; cols_scaled(find(I(central,:) > 0)) = 1; else, cols_scaled = []; end num_trials = round(opt.trial_coef * n); if opt.verbose, fprintf(1,'(Allocating memory...'); end nullspace(size(M,1),num_trials) = 0; % Memory allocation: at least this % because at least one column is % added per one 4-tuple. width = 0; if opt.verbose, fprintf(1, ')'); end tenth = .1; % because of the first % result.used = 0; result.failed = 0; for i = 1:num_trials % choose a 4/max-tuple cols = 1:n; rows = 1:m; cols_chosen = []; t=1; failed = 0; if central, scaled_ensured = 0; else scaled_ensured = 1; % trial version: no scale controling when cutting end for t = 1:4 % choose one column, cut useless parts etc. [c, cols] = random_element(cols); cols_chosen = [cols_chosen c]; % check just added column rows = intersect(rows, find(I(:,c) > 0)); if t < 4, [rows, cols, scaled_ensured] = cut_useless(I, cols_scaled, ... cols_chosen, rows, cols, 4-t, scaled_ensured); end if isempty(rows), failed = 1; break; end end if ~failed % use the 4/max-tuple d = depths(rows,cols_chosen); % see ``debug code'' in the comment lower rowsbig = k2i(rows); submatrix=[]; for j=1:length(cols_chosen) % 4, submatrix=[ submatrix ... spread_depths_col(M(rowsbig,cols_chosen(j)), d(:,j)) ]; end debug=1; if debug, if size(submatrix, 1)<=size(submatrix,2) & opt.verbose fprintf(1,'-'); end;end subnull = nulleps(submatrix,opt.threshold); %svd(submatrix) if size(subnull,2)>0 & ( use_maxtuples | ... size(submatrix,1) == size(submatrix,2) + size(subnull,2)) nulltemp = zeros(size(M,1),size(subnull,2)); nulltemp(rowsbig,:) = subnull; % * (length(rows)/m); % weighting if width+size(nulltemp,2) > size(nullspace,2) % Memory allocation: if opt.verbose, fprintf(1,'(Allocating memory...)'); end mean_added = width/i; nullspace(size(M,1), size(nullspace,2) ... + round(mean_added * (num_trials-i))) = 0; end nullspace(:, width+1 : width+size(nulltemp,2)) = nulltemp; width = width +size(nulltemp,2); result.used = result.used +1; if mod(result.used, show_mod)==0 & opt.verbose, fprintf(1,'.'); end end else result.failed = result.failed +1; end if i/num_trials > .1*tenth if opt.verbose, fprintf(1,'%d%%', tenth*10); end if tenth < 1, tenth=0; end tenth = tenth + 1; end end if size(nullspace,2) > width, % cut off unused allocated memory if opt.verbose, fprintf(1,'(Cutting unused memory...'); end nullspace = nullspace(:,1:width); if opt.verbose, fprintf(1, ')'); end end if opt.verbose, fprintf(1, ['(' num2str(toc) ' sec)\n']); end result.tried = i; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % debug code % if size(d, 1) == 1, bla; end % if sum(d(1,:)==0) > 2, blabla; end % if use_maxtuples | ... % size(d,1)*3 > size(d,2) + sum(d(:)==0)... % i.e. size(submatrix,1)> % ... % size(submatrix,2) % - sum(cols_scaled(cols_chosen)==0) % i.e. subtract 1 per each % % column full of zeros %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [rows, cols, scaled_ensured] = cut_useless( ... %) I, cols_scaled, ... % this is always same cols_chosen, rows, cols, demanded, scaled_ensured) if ~scaled_ensured % check scaled columns if length(rows) == 2, demanded_scaled = 3; demanded_rows = 2; else demanded_scaled = 2; demanded_rows = 3; end cols_scaled_chosen = sum(cols_scaled(cols_chosen) > 0); % if no unscaled are allowed, they must be all cut if demanded == demanded_scaled - cols_scaled_chosen, cols = intersect(cols, find(cols_scaled > 0)); scaled_ensured = 1; end else demanded_rows = 2; end % check columns cols = cols(find(sum(I(rows,cols)) >= demanded_rows)); % check rows rows = rows(find(sum(I(rows,cols)') >= demanded)); function [element, rest] = random_element(set) % Take a random element out of a set. element = set(random_int(1, length(set))); rest = setdiff(set, element); function y = random_int(from,to) y = floor(from + (1 + to - from)*rand); function [N,s] = nulleps(M,tol) % Find the nullspace of M. This is the regular nullspace, augmented by % vectors that aren't really in the nullspace, but have low singular % values associated with them. tol is the threshold on these singular values. [u,s,v] = svd(M); sigsvs = sum(diag(s)>tol); N = u(:,sigsvs+1:size(u,2));