├── tracking ├── mexResize.mexw64 ├── gradientMex.mexw64 ├── opencv_core242.dll ├── opencv_imgproc242.dll ├── utility │ ├── interp2.dll │ ├── interp2.mexa64 │ ├── interp2.mexglx │ ├── interp2.mexw64 │ ├── affparaminv.m │ ├── affwarpimg.m │ ├── affparam2mat.m │ ├── warpimg.m │ ├── affparam2geom.m │ ├── box_to_p.m │ ├── p_to_box.m │ └── interp2.cpp ├── gaussian_correlation_scale_single.m ├── README.md ├── getP.m ├── display_statistics.m ├── gaussianResponse.m ├── get_axis_aligned_BB.m ├── getDesiredResponse.m ├── cropFilterResponse.m ├── getColourMap.m ├── mergeResponses.m ├── readParams.m ├── computeHistogram.m ├── gaussian_correlation.m ├── getFeatureMap.m ├── getCenterLikelihood.m ├── isToolboxAvailable.m ├── getSubwindow.m ├── precision_plot.m ├── getScalePatch.m ├── params.txt ├── wrappers.hpp ├── updateHistModel.m ├── getScaleSubwindow_v1.m ├── get_feature_map.m ├── getScaleSubwindow.m ├── run_KCC.m ├── initializeAllAreas.m ├── fhog.m ├── unfreezeColors.m ├── freezeColors.m └── trackerMain_otb_wangchen.m ├── recognition ├── README.md ├── analyse_parameters.m ├── find_parameter.m ├── gaussian_kernel.m ├── kcc.m ├── run_me.m ├── matrix2latex │ ├── license.txt │ └── matrix2latex.m ├── natsortfiles │ ├── license.txt │ ├── natsortfiles_doc.m │ ├── natsortfiles.m │ ├── natsort.m │ └── html │ │ └── natsortfiles_doc.html ├── kcc_train.m ├── .gitignore ├── show_example.m ├── data_conversion.m ├── activity_recognition.m └── show_results.m ├── README.md └── LICENSE /tracking/mexResize.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/mexResize.mexw64 -------------------------------------------------------------------------------- /tracking/gradientMex.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/gradientMex.mexw64 -------------------------------------------------------------------------------- /tracking/opencv_core242.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/opencv_core242.dll -------------------------------------------------------------------------------- /tracking/opencv_imgproc242.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/opencv_imgproc242.dll -------------------------------------------------------------------------------- /tracking/utility/interp2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/utility/interp2.dll -------------------------------------------------------------------------------- /tracking/utility/interp2.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/utility/interp2.mexa64 -------------------------------------------------------------------------------- /tracking/utility/interp2.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/utility/interp2.mexglx -------------------------------------------------------------------------------- /tracking/utility/interp2.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sair-lab/KCC/HEAD/tracking/utility/interp2.mexw64 -------------------------------------------------------------------------------- /tracking/gaussian_correlation_scale_single.m: -------------------------------------------------------------------------------- 1 | function kf = gaussian_correlation_scale_single(base, y, sigma) 2 | 3 | N = size(y,1) * size(y,2);%*size(y,3); 4 | for i =1:size(base,2) 5 | n = sum(sum(sum((base(:,i) - y).^2)))/N^2; 6 | k(i) = exp(-n / sigma^2 ) ; 7 | end 8 | 9 | kf = fft(k'); 10 | end 11 | -------------------------------------------------------------------------------- /tracking/README.md: -------------------------------------------------------------------------------- 1 | # Visual Tracking Using Kernel Cross-Correlator (KCC) 2 | 3 | This tracker can be inserted into the tracker benchmark (MATLAB version) directly: 4 | 5 | https://sites.google.com/site/trackerbenchmark/benchmarks/v10 6 | 7 | To run it, you may download the whole repo as: 8 | 9 | git clone https://github.com/wang-chen/KCC.git 10 | 11 | Then put it into the tracker folder and follow the instructions of the benchmark. 12 | -------------------------------------------------------------------------------- /tracking/getP.m: -------------------------------------------------------------------------------- 1 | function P = getP(histogram, h, w, bin_indices, grayscale_sequence) 2 | %GETP computes the scores given the histogram 3 | % query the hist for the probability of each pixel 4 | if grayscale_sequence 5 | hist_indices = bin_indices; 6 | else 7 | hist_indices = sub2ind(size(histogram), bin_indices(:,1), bin_indices(:,2), bin_indices(:,3)); 8 | end 9 | 10 | % shape it as a matrix 11 | P = reshape(histogram(hist_indices), h, w); 12 | end -------------------------------------------------------------------------------- /tracking/utility/affparaminv.m: -------------------------------------------------------------------------------- 1 | function q = affparaminv(p,q) 2 | % function q = affparaminv(p[, q]) 3 | % 4 | % p(6,n) : [dx dy sc th sr phi]' 5 | % q(6,n) : [q(1) q(3) q(4); q(2) q(5) q(6)] 6 | 7 | % Copyright (C) Jongwoo Lim and David Ross. All rights reserved. 8 | 9 | if (length(p) == 6) 10 | p = p(:); 11 | end 12 | if (nargin > 1) 13 | q = inv([p(3) p(4); p(5) p(6)]) * [q(1)-p(1) q(3:4); q(2)-p(2) q(5:6)]; 14 | else 15 | q = inv([p(3) p(4); p(5) p(6)]) * [-p(1) 1 0; -p(2) 0 1]; 16 | end 17 | q = q([1,2,3,5,4,6]); 18 | -------------------------------------------------------------------------------- /tracking/display_statistics.m: -------------------------------------------------------------------------------- 1 | function display_statistics(name, precision, reinitializations, fps) 2 | %print statistics to command window 3 | str = sprintf('Overlap:% 1.3f', precision); 4 | 5 | if ~isnan(reinitializations), 6 | if reinitializations == round(reinitializations), %prettier for integer values 7 | str = [str, sprintf(', reinitializations:% 2i', reinitializations)]; 8 | else 9 | str = [str, sprintf(', reinitializations:% 1.2f', reinitializations)]; 10 | end 11 | end 12 | 13 | fprintf('%12s - %s, FPS:% 4.2f\n', name, str, fps) 14 | end 15 | -------------------------------------------------------------------------------- /tracking/gaussianResponse.m: -------------------------------------------------------------------------------- 1 | function y = gaussianResponse(rect_size, sigma) 2 | %GAUSSIANRESPONSE create the (fixed) target response of the correlation filter response 3 | half = floor((rect_size-1) / 2); 4 | i_range = -half(1):half(1); 5 | j_range = -half(2):half(2); 6 | [i, j] = ndgrid(i_range, j_range); 7 | i_mod_range = mod_one(i_range, rect_size(1)); 8 | j_mod_range = mod_one(j_range, rect_size(2)); 9 | y = zeros(rect_size); 10 | y(i_mod_range, j_mod_range) = exp(-(i.^2 + j.^2) / (2 * sigma^2)); 11 | end 12 | 13 | function y = mod_one(a, b) 14 | y = mod(a-1, b)+1; 15 | end 16 | -------------------------------------------------------------------------------- /tracking/get_axis_aligned_BB.m: -------------------------------------------------------------------------------- 1 | function [cx, cy, w, h] = get_axis_aligned_BB(region) 2 | % GETAXISALIGNEDBB extracts an axis aligned bbox from the ground truth REGION with same area as the rotated one 3 | cx = mean(region(1:2:end)); 4 | cy = mean(region(2:2:end)); 5 | x1 = min(region(1:2:end)); 6 | x2 = max(region(1:2:end)); 7 | y1 = min(region(2:2:end)); 8 | y2 = max(region(2:2:end)); 9 | A1 = norm(region(1:2) - region(3:4)) * norm(region(3:4) - region(5:6)); 10 | A2 = (x2 - x1) * (y2 - y1); 11 | s = sqrt(A1/A2); 12 | w = s * (x2 - x1) + 1; 13 | h = s * (y2 - y1) + 1; 14 | end 15 | -------------------------------------------------------------------------------- /tracking/getDesiredResponse.m: -------------------------------------------------------------------------------- 1 | function [desiredResponse, x0, y0] = getDesiredResponse(saliency_map, bg_area, target_sz, p) 2 | % GETDESIREDRESPONSE is a wrapper for getGaussian, that computes the (object-centered) desired response 3 | 4 | % If the saliency patch is empty, use a patch centered desired response only for one frame 5 | if(sum(sum(saliency_map))==0) 6 | p.gaussianType = 'bboxCentered'; 7 | [desiredResponse, ~, ~] = getGaussian(saliency_map, bg_area, target_sz, p); 8 | x0 = 0; 9 | y0 = 0; 10 | p.gaussianType = 'objectCentered'; 11 | else 12 | [desiredResponse, x0, y0] = getGaussian(saliency_map, bg_area, target_sz, p); 13 | end 14 | 15 | end -------------------------------------------------------------------------------- /tracking/utility/affwarpimg.m: -------------------------------------------------------------------------------- 1 | function wimg = affwarpimg(img, p, sz) 2 | % function wimg = affwarpimg(img, p, sz) 3 | % 4 | % img(h,w) 5 | % p(6,n) : mat format affine parameter 6 | % sz(th,tw) 7 | % 8 | 9 | %% Copyright (C) Jongwoo Lim and David Ross. 10 | %% All rights reserved. 11 | 12 | 13 | if (nargin < 3) 14 | sz = size(img); 15 | end 16 | if (size(p,1) == 1) 17 | p = p(:); 18 | end 19 | w = sz(2); h = sz(1); n = size(p,2); 20 | [x,y] = meshgrid(1:w, 1:h); 21 | pos = reshape(cat(2, ones(h*w,1),x(:),y(:)) ... 22 | * [p(1,:) p(2,:); p(3:4,:) p(5:6,:)], [h,w,n,2]); 23 | wimg = squeeze(interp2(img, pos(:,:,:,1), pos(:,:,:,2))); 24 | wimg(find(isnan(wimg))) = 0; 25 | -------------------------------------------------------------------------------- /tracking/utility/affparam2mat.m: -------------------------------------------------------------------------------- 1 | function q = affparam2mat(p) 2 | 3 | % Copyright (C) Jongwoo Lim and David Ross. All rights reserved. 4 | 5 | 6 | sz = size(p); 7 | if (length(p(:)) == 6) 8 | p = p(:); 9 | end 10 | s = p(3,:); th = p(4,:); r = p(5,:); phi = p(6,:); 11 | cth = cos(th); sth = sin(th); cph = cos(phi); sph = sin(phi); 12 | ccc = cth.*cph.*cph; ccs = cth.*cph.*sph; css = cth.*sph.*sph; 13 | scc = sth.*cph.*cph; scs = sth.*cph.*sph; sss = sth.*sph.*sph; 14 | q(1,:) = p(1,:); q(2,:) = p(2,:); 15 | q(3,:) = s.*(ccc +scs +r.*(css -scs)); q(4,:) = s.*(r.*(ccs -scc) -ccs -sss); 16 | q(5,:) = s.*(scc -ccs +r.*(ccs +sss)); q(6,:) = s.*(r.*(ccc +scs) -scs +css); 17 | q = reshape(q, sz); 18 | -------------------------------------------------------------------------------- /recognition/README.md: -------------------------------------------------------------------------------- 1 | # Activity Recognition Using Kernel Cross-Correlator (KCC) 2 | 3 | This part requires the following WARD 1.0 dataset: 4 | 5 | https://people.eecs.berkeley.edu/~yang/software/WAR/index.html 6 | 7 | Unzip the databse to recognition folder, so that the directory looks like: 8 | 9 | KCC 10 | ├───recognition 11 | │ ├───matrix2latex 12 | │ ├───natsortfiles 13 | │ │ └───html 14 | │ └───WARD1.0 15 | │ ├───Subject1 16 | │ ├───Subject10 17 | │ ├───Subject11 18 | │ ├───Subject12 19 | │ ├───Subject13 20 | | ... 21 | └───tracking 22 | └───utility 23 | 24 | Then you may find some examples in the run_me.m file 25 | -------------------------------------------------------------------------------- /tracking/utility/warpimg.m: -------------------------------------------------------------------------------- 1 | function wimg = warpimg(img, p, sz) 2 | %% Copyright (C) 2005 Jongwoo Lim and David Ross. 3 | %% All rights reserved. 4 | 5 | if (nargin < 3) 6 | sz = size(img); 7 | end 8 | if (size(p,1) == 1) 9 | p = p(:); 10 | end 11 | w = sz(2); h = sz(1); n = size(p,2); 12 | [x,y] = meshgrid([1:w]-w/2, [1:h]-h/2); 13 | pos = reshape(cat(2, ones(h*w,1),x(:),y(:)) ... 14 | * [p(1,:) p(2,:); p(3:4,:) p(5:6,:)], [h,w,n,2]); 15 | wimg = squeeze(interp2(img, pos(:,:,:,1), pos(:,:,:,2))); 16 | 17 | 18 | wimg(find(isnan(wimg))) = 0; 19 | 20 | % B = SQUEEZE(A) returns an array B with the same elements as 21 | % A but with all the singleton dimensions removed. A singleton 22 | % is a dimension such that size(A,dim)==1; 23 | 24 | -------------------------------------------------------------------------------- /tracking/cropFilterResponse.m: -------------------------------------------------------------------------------- 1 | function new_response = cropFilterResponse(response_cf, response_size) 2 | %CROPFILTERRESPONSE makes RESPONSE_CF of size RESPONSE_SIZE (i.e. same size of colour response) 3 | 4 | [h,w] = size(response_cf); 5 | b = response_size(1); 6 | a = response_size(2); 7 | 8 | % a and b must be odd, as we want an exact center 9 | if ~all_odd([a, b]) 10 | error('dimensions must be odd'); 11 | end 12 | half_width = floor(a/2); 13 | half_height = floor(b/2); 14 | 15 | new_response = response_cf(... 16 | mod_one(-half_height:half_height, h), ... 17 | mod_one(-half_width:half_width, w)); 18 | end 19 | 20 | function y = mod_one(a, b) 21 | y = mod(a-1, b)+1; 22 | end 23 | 24 | function y = all_odd(x) 25 | y = all(mod(x, 2) == 1); 26 | end 27 | -------------------------------------------------------------------------------- /tracking/getColourMap.m: -------------------------------------------------------------------------------- 1 | function [P_O] = getColourMap(patch, bg_hist, fg_hist, n_bins, grayscale_sequence) 2 | %% GETCOLOURMAP computes pixel-wise probabilities (PwP) given PATCH and models BG_HIST and FG_HIST 3 | % check whether the patch has 3 channels 4 | [h, w, d] = size(patch); 5 | % figure out which bin each pixel falls into 6 | bin_width = 256/n_bins; 7 | % convert image to d channels array 8 | patch_array = reshape(double(patch), w*h, d); 9 | % to which bin each pixel (for all d channels) belongs to 10 | bin_indices = floor(patch_array/bin_width) + 1; 11 | % Get pixel-wise posteriors (PwP) 12 | P_bg = getP(bg_hist, h, w, bin_indices, grayscale_sequence); 13 | P_fg = getP(fg_hist, h, w, bin_indices, grayscale_sequence); 14 | 15 | % Object-likelihood map 16 | P_O = P_fg ./ (P_fg + P_bg); 17 | end 18 | -------------------------------------------------------------------------------- /tracking/utility/affparam2geom.m: -------------------------------------------------------------------------------- 1 | function q = affparam2geom(p) 2 | 3 | % Copyright (C) Jongwoo Lim and David Ross. All rights reserved. 4 | 5 | A = [ p(3), p(4); p(5), p(6) ]; 6 | 7 | [U,S,V] = svd(A); 8 | if (det(U) < 0) 9 | U = U(:,2:-1:1); V = V(:,2:-1:1); S = S(2:-1:1,2:-1:1); 10 | end 11 | 12 | 13 | q(1) = p(1); 14 | q(2) = p(2); 15 | 16 | 17 | q(4) = atan2(U(2,1)*V(1,1)+U(2,2)*V(1,2), U(1,1)*V(1,1)+U(1,2)*V(1,2)); 18 | 19 | phi = atan2(V(1,2),V(1,1)); 20 | if (phi <= -pi/2) 21 | c = cos(-pi/2); s = sin(-pi/2); 22 | R = [c -s; s c]; V = V * R; S = R'*S*R; 23 | end 24 | if (phi >= pi/2) 25 | c = cos(pi/2); s = sin(pi/2); 26 | R = [c -s; s c]; V = V * R; S = R'*S*R; 27 | end 28 | 29 | 30 | q(3) = S(1,1); 31 | q(5) = S(2,2)/S(1,1); 32 | 33 | q(6) = atan2(V(1,2),V(1,1)); 34 | 35 | q = reshape(q, size(p)); 36 | -------------------------------------------------------------------------------- /tracking/mergeResponses.m: -------------------------------------------------------------------------------- 1 | function [response] = mergeResponses(response_cf, response_pwp, alpha, merge_method) 2 | %MERGERESPONSES interpolates the two responses with the hyperparameter ALPHA 3 | if strcmp(merge_method, 'const_factor') 4 | response = (1 - alpha) * response_cf + alpha * response_pwp; 5 | end 6 | 7 | if strcmp(merge_method, 'fit_gaussian') 8 | [~, cov2D_cf] = fitGaussian(response_cf); 9 | [~, cov2D_pwp] = fitGaussian(response_pwp); 10 | response_u = ones(size(response_cf)); 11 | [~, cov2D_u] = fitGaussian(response_u); 12 | w_cf = 1 - sqrt(det(cov2D_cf)/det(cov2D_u)); 13 | w_pwp = 1 - sqrt(det(cov2D_pwp)/det(cov2D_u)); 14 | sum_cf_pwp = w_cf + w_pwp; 15 | w_cf = w_cf / sum_cf_pwp; 16 | w_pwp = w_pwp / sum_cf_pwp; 17 | 18 | response = w_cf * response_cf + w_pwp * response_pwp; 19 | fprintf('w_cf: %.3f w_pwp: %.3f\n', w_cf, w_pwp); 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /tracking/readParams.m: -------------------------------------------------------------------------------- 1 | function params = readParams(params_file_name, hp_name, hp_value) 2 | % read params.txt and convert into struct 3 | fparams = fopen(params_file_name); 4 | C = textscan(fparams, '%s', 'Delimiter', '', 'CommentStyle', '%'); 5 | fclose(fparams); 6 | % feed the lines one by one into eval to create the variables in the MATLAB workspace: 7 | cellfun(@evalc, C{1}, 'UniformOutput', false); 8 | % clear all the variables not in the params file 9 | clear C fparams 10 | % save current workspace in a struct 11 | this_workspace = evalin('caller','who'); 12 | % save everything in a struct 13 | for i=1:size(this_workspace,1) 14 | thisvar=evalin('caller', this_workspace{i}); 15 | params.(this_workspace{i})=thisvar; 16 | end 17 | 18 | if(isfield(params,'ans')) 19 | rmfield(params,'ans'); 20 | end 21 | 22 | if nargin>1 23 | % if hyperparam is set: override default parameters with specified one 24 | params.(hp_name) = hp_value; 25 | end 26 | end -------------------------------------------------------------------------------- /tracking/computeHistogram.m: -------------------------------------------------------------------------------- 1 | function histogram = computeHistogram(patch, mask, n_bins, grayscale_sequence) 2 | %COMPUTEHISTOGRAM creates a colour (or grayscale) histogram of an image patch 3 | % MASK has the same size as the image patch and selects what should 4 | % be used when computing the histogram (i.e. out-of-frame regions are ignored) 5 | 6 | [h, w, d] = size(patch); 7 | 8 | assert(all([h w]==size(mask)) == 1, 'mask and image are not the same size'); 9 | 10 | bin_width = 256/n_bins; 11 | 12 | % convert image to 1d array with same n channels of img patch 13 | patch_array = reshape(double(patch), w*h, d); 14 | % compute to which bin each pixel (for all 3 channels) belongs to 15 | bin_indices = floor(patch_array/bin_width) + 1; 16 | 17 | if grayscale_sequence 18 | histogram = accumarray(bin_indices, mask(:), [n_bins 1])/sum(mask(:)); 19 | else 20 | % the histogram is a cube of side n_bins 21 | histogram = accumarray(bin_indices, mask(:), [n_bins n_bins n_bins])/sum(mask(:)); 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /tracking/gaussian_correlation.m: -------------------------------------------------------------------------------- 1 | function kf = gaussian_correlation(xf, yf, sigma) 2 | %GAUSSIAN_CORRELATION Gaussian Kernel at all shifts, i.e. kernel correlation. 3 | % Evaluates a Gaussian kernel with bandwidth SIGMA for all relative 4 | % shifts between input images X and Y, which must both be MxN. They must 5 | % also be periodic (ie., pre-processed with a cosine window). The result 6 | % is an MxN map of responses. 7 | % 8 | % Inputs and output are all in the Fourier domain. 9 | % 10 | % Joao F. Henriques, 2014 11 | % http://www.isr.uc.pt/~henriques/ 12 | 13 | N = size(xf,1) * size(xf,2); 14 | xx = xf(:)' * xf(:) / N; %squared norm of x 15 | yy = yf(:)' * yf(:) / N; %squared norm of y 16 | 17 | %cross-correlation term in Fourier domain 18 | xyf = xf .* conj(yf); 19 | xy = sum(real(ifft2(xyf)), 3); %to spatial domain 20 | 21 | %calculate gaussian response for all positions, then go back to the 22 | %Fourier domain 23 | kf = fft2(exp(-1 / sigma^2 * max(0, (xx + yy - 2 * xy) / numel(xf)))); 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /tracking/getFeatureMap.m: -------------------------------------------------------------------------------- 1 | function out = getFeatureMap(im_patch, feature_type, cf_response_size, hog_cell_size) 2 | 3 | % code from DSST 4 | 5 | % allocate space 6 | switch feature_type 7 | case 'fhog' 8 | temp = fhog(single(im_patch), hog_cell_size); 9 | h = cf_response_size(1); 10 | w = cf_response_size(2); 11 | out = zeros(h, w, 28, 'single'); 12 | out(:,:,2:28) = temp(:,:,1:27); 13 | if hog_cell_size > 1 14 | im_patch = mexResize(im_patch, [h, w] ,'auto'); 15 | end 16 | % if color image 17 | if size(im_patch, 3) > 1 18 | im_patch = rgb2gray(im_patch); 19 | end 20 | out(:,:,1) = single(im_patch)/255 - 0.5; 21 | case 'gray' 22 | if hog_cell_size > 1, im_patch = mexResize(im_patch,cf_response_size,'auto'); end 23 | if size(im_patch, 3) == 1 24 | out = single(im_patch)/255 - 0.5; 25 | else 26 | out = single(rgb2gray(im_patch))/255 - 0.5; 27 | end 28 | end 29 | 30 | end 31 | 32 | -------------------------------------------------------------------------------- /recognition/analyse_parameters.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | % clc 19 | % clear 20 | load('performances_refine_refin.mat'); 21 | plot3(performances(:,end-1), performances(:,end), performances(:,2),'.') 22 | performances(:,[end-1,end,2]) 23 | max(performances(:,2)) -------------------------------------------------------------------------------- /tracking/getCenterLikelihood.m: -------------------------------------------------------------------------------- 1 | function center_likelihood = getCenterLikelihood(object_likelihood, m) 2 | %GETCENTERLIKELIHOOD computes the sum over rectangles of size M. 3 | % CENTER_LIKELIHOOD is the 'colour response' 4 | [h,w] = size(object_likelihood); 5 | n1 = h - m(1) + 1; 6 | n2 = w - m(2) + 1; 7 | 8 | %% integral images 9 | % compute summed area table 10 | % SAT = zeros(h, w); 11 | % for y=1:h 12 | % for x=1:w 13 | % if x>1, SAT_left = SAT(y,x-1); 14 | % else SAT_left = 0; end 15 | % if y>1, SAT_up = SAT(y-1,x); 16 | % else SAT_up = 0; end 17 | % if y>1 && x>1, SAT_left_up = SAT(y-1,x-1); 18 | % else SAT_left_up = 0; end 19 | % 20 | % SAT(y,x) = object_likelihood(y,x) + SAT_left + SAT_up - SAT_left_up; 21 | % end 22 | % end 23 | % SAT = padarray(SAT,[1 1], 'pre'); 24 | 25 | %% equivalent MATLAB function 26 | SAT = integralImage(object_likelihood); 27 | i = 1:n1; 28 | j = 1:n2; 29 | center_likelihood = (SAT(i,j) + SAT(i+m(1), j+m(2)) - SAT(i+m(1), j) - SAT(i, j+m(2))) / prod(m); 30 | end 31 | -------------------------------------------------------------------------------- /tracking/utility/box_to_p.m: -------------------------------------------------------------------------------- 1 | function [ p ] = box_to_p( varargin ) 2 | %BOX_TO_P Summary of this function goes here 3 | % Detailed explanation goes here 4 | % function p_to_box(width,height, param, properties) 5 | % ([width,height], param, properties) 6 | % 7 | % 8 | 9 | %---------------------------------------------------------- 10 | % Process the input. 11 | %---------------------------------------------------------- 12 | if (length(varargin{1}) == 2) 13 | w = varargin{1}(1); 14 | h = varargin{1}(2); 15 | varargin(1) = []; 16 | else 17 | [w,h] = deal(varargin{1:2}); 18 | varargin(1:2) = []; 19 | end 20 | 21 | 22 | if (length(varargin) < 1 )%|| any(length(varargin{1}) ~= 2)) 23 | M = [0,1,0; 0,0,1]; 24 | else 25 | corners = cell2mat(varargin{1}); 26 | varargin(1) = []; 27 | % M = [p(1) p(3) p(4); p(2) p(5) p(6)]; 28 | end 29 | 30 | %---------------------------------------------------------- 31 | % Draw the box. 32 | %---------------------------------------------------------- 33 | W = [ 1,-w/2,-h/2; 1,w/2,-h/2; 1,w/2,h/2; 1,-w/2,h/2; 1,-w/2,-h/2 ]'; 34 | M = corners/W; 35 | 36 | p = [M(1,1), M(2,1),M(1,2),M(1,3),M(2,2),M(2,3) ]; 37 | 38 | end 39 | 40 | -------------------------------------------------------------------------------- /tracking/utility/p_to_box.m: -------------------------------------------------------------------------------- 1 | function [ center corners ] = p_to_box(varargin) 2 | % function p_to_box(width,height, param, properties) 3 | % ([width,height], param, properties) 4 | % 5 | % 6 | 7 | %---------------------------------------------------------- 8 | % Process the input. 9 | %---------------------------------------------------------- 10 | if (length(varargin{1}) == 2) 11 | w = varargin{1}(1); 12 | h = varargin{1}(2); 13 | varargin(1) = []; 14 | else 15 | [w,h] = deal(varargin{1:2}); 16 | varargin(1:2) = []; 17 | end 18 | 19 | 20 | if (length(varargin) < 1 || any(length(varargin{1}) ~= 6)) 21 | M = [0,1,0; 0,0,1]; 22 | else 23 | p = varargin{1}; 24 | if (length(varargin) > 1 && strcmp(varargin{2},'geom')) 25 | p = affparam2mat(p); 26 | varargin(1:2) = []; 27 | else 28 | varargin(1) = []; 29 | end 30 | M = [p(1) p(3) p(4); p(2) p(5) p(6)]; 31 | end 32 | 33 | %---------------------------------------------------------- 34 | % Draw the box. 35 | %---------------------------------------------------------- 36 | corners = [ 1,-w/2,-h/2; 1,w/2,-h/2; 1,w/2,h/2; 1,-w/2,h/2; 1,-w/2,-h/2 ]'; 37 | corners = M * corners; 38 | center = mean(corners(:,1:4),2); 39 | -------------------------------------------------------------------------------- /recognition/find_parameter.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | clc 19 | clear 20 | lambda = 0.0014:0.0001:0.0020; 21 | sigma = 0.5:0.1:1.1; 22 | 23 | performances=[]; 24 | for i = 1:numel(lambda) 25 | for j = 1:numel(sigma) 26 | performance = activity_recognition(lambda(i), sigma(j)); 27 | performances = [performance; performances]; 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /recognition/gaussian_kernel.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | function kf = gaussian_kernel(xf, yf, sigma) 19 | % Calculating the gaussian kernel vertor 20 | % Copyright Wang Chen, Nanyang Technoglogical University 21 | 22 | N = numel(xf); 23 | xx = xf(:)' * xf(:) / N; 24 | yy = yf(:)' * yf(:) / N; 25 | xy = mean((ifft(xf .* conj(yf))),2); 26 | kf = exp(-1 / sigma^2 * (xx + yy - 2 * xy) / N); 27 | end 28 | 29 | -------------------------------------------------------------------------------- /recognition/kcc.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | function [response, output] = kcc(test, correlator) 18 | % Calculating the response 19 | % Copyright Wang Chen, Nanyang Technoglogical University 20 | test_fft = fft(test); 21 | kernel_fft = fft(gaussian_kernel(test_fft, correlator.sample_fft, correlator.sigma)); 22 | output = abs(ifft(correlator.correlator_fft.*kernel_fft)); 23 | response = max(output);%/sum(output); 24 | end 25 | 26 | -------------------------------------------------------------------------------- /recognition/run_me.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | data_conversion; % convert database to compatible format 18 | 19 | activity_recognition; % run recognition demo and show results 20 | 21 | %% you may also run show_example after running data_conversion to visulize the signals. 22 | show_example 23 | 24 | %% Example to use KCC similarity 25 | lambda = 0.0015; 26 | sigma = 1; 27 | 28 | correlator = kcc_train(example1, lambda, sigma); 29 | 30 | similarity_12 = kcc(example2, correlator) 31 | similarity_13 = kcc(example3, correlator) -------------------------------------------------------------------------------- /recognition/matrix2latex/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Moritz Koehler 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /tracking/isToolboxAvailable.m: -------------------------------------------------------------------------------- 1 | function result = isToolboxAvailable(toolboxName,action) 2 | %% check if an specific toolbox exists 3 | % 4 | % This small piece of code checks to find whether a specific toolbox is 5 | % installed on MATLAB. 6 | % 7 | % The input is the name of the toolbox as a string 8 | % 9 | % The output is 1 if the toolbox is found and 0 otherwise 10 | % 11 | % Example: 12 | % 13 | % result = isToolboxAvailable('Image Processing Toolbox','warning') 14 | % 15 | % ----------------------------------------------- 16 | % code by: Reza Ahmadzadeh (reza.ahmadzadeh@iit.it) 17 | % ----------------------------------------------- 18 | % 19 | %% check the input arguments 20 | if nargin < 1 || nargin > 2 21 | error('usage: isToolboxAvailable(toolboxName,action)'); 22 | elseif nargin == 1 23 | action = 'warning'; 24 | end; 25 | 26 | %% Find the toolbox and give proper output 27 | v_=ver; 28 | [installedToolboxes{1:length(v_)}] = deal(v_.Name); 29 | result = all(ismember(toolboxName,installedToolboxes)); 30 | switch action 31 | case 'error' 32 | % if you need to end the program you can use the following line of code 33 | assert(result,['Error! ' toolboxName ' is not installed!']); 34 | case 'warning' 35 | % if you need to just give a warning you can use the following line of code 36 | if ~result 37 | warning([toolboxName ' is not installed!']); 38 | end 39 | otherwise 40 | end 41 | end -------------------------------------------------------------------------------- /recognition/natsortfiles/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Stephen Cobeldick 2 | Copyright (c) 2016, Stephen Cobeldick 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the distribution 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /tracking/getSubwindow.m: -------------------------------------------------------------------------------- 1 | function im_patch = getSubwindow(im, pos, model_sz, scaled_sz) 2 | %GET_SUBWINDOW Obtain image sub-window, padding is done by replicating border values. 3 | % Returns sub-window of image IM centered at POS ([y, x] coordinates), 4 | % with size MODEL_SZ ([height, width]). If any pixels are outside of the image, 5 | % they will replicate the values at the borders 6 | 7 | % with 3 input, no scale. With 4 params, scale adaptation 8 | if nargin < 4, sz = model_sz; 9 | else, sz = scaled_sz; 10 | end 11 | 12 | %make sure the size is not to small 13 | sz = max(sz, 2); 14 | %if sz(1) < 1, sz(1) = 2; end; 15 | %if sz(2) < 1, sz(2) = 2; end; 16 | 17 | %xs = floor(pos(2)) + (1:sz(2)) - floor(sz(2)/2); 18 | %ys = floor(pos(1)) + (1:sz(1)) - floor(sz(1)/2); 19 | xs = round(pos(2) + (1:sz(2)) - sz(2)/2); 20 | ys = round(pos(1) + (1:sz(1)) - sz(1)/2); 21 | 22 | %check for out-of-bounds coordinates, and set them to the values at 23 | %the borders 24 | xs(xs < 1) = 1; 25 | ys(ys < 1) = 1; 26 | xs(xs > size(im,2)) = size(im,2); 27 | ys(ys > size(im,1)) = size(im,1); 28 | 29 | %extract image 30 | im_patch_original = im(ys, xs, :); 31 | 32 | % (if rescaling is introduced) resize image to model size 33 | % im_patch = imresize(im_patch, model_sz, 'bilinear'); 34 | if nargin>=4 35 | % im_patch = mexResize(im_patch_original, model_sz, 'auto'); 36 | im_patch = mexResize(im_patch_original, model_sz, 'auto'); 37 | else 38 | im_patch = im_patch_original; 39 | end 40 | 41 | end 42 | 43 | -------------------------------------------------------------------------------- /recognition/kcc_train.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | function correlator = kcc_train(sample, lambda, sigma) 19 | % Training the correlator based on one sample 20 | % Copyright Wang Chen, Nanyang Technoglogical University 21 | if nargin < 3 22 | sigma = 0.3; 23 | end 24 | if nargin < 2 25 | lambda = 0.1; 26 | end 27 | 28 | correlator.sigma = sigma; 29 | target_fft = ones(size(sample,1),1); 30 | correlator.sample_fft = fft(sample); 31 | kernel_fft = fft(gaussian_kernel(correlator.sample_fft, correlator.sample_fft, correlator.sigma)); 32 | correlator.correlator_fft = target_fft./(kernel_fft + lambda); 33 | end 34 | 35 | -------------------------------------------------------------------------------- /tracking/precision_plot.m: -------------------------------------------------------------------------------- 1 | function precisions = precision_plot(positions, ground_truth, title, show) 2 | %PRECISION_PLOT 3 | % Calculates precision for a series of distance thresholds (percentage of 4 | % frames where the distance to the ground truth is within the threshold). 5 | % The results are shown in a new figure if SHOW is true. 6 | % 7 | % Accepts positions and ground truth as Nx2 matrices (for N frames), and 8 | % a title string. 9 | % 10 | % Joao F. Henriques, 2014 11 | % http://www.isr.uc.pt/~henriques/ 12 | 13 | 14 | max_threshold = 50; %used for graphs in the paper 15 | 16 | 17 | precisions = zeros(max_threshold, 1); 18 | 19 | if size(positions,1) ~= size(ground_truth,1), 20 | % fprintf('%12s - Number of ground truth frames does not match number of tracked frames.\n', title) 21 | 22 | %just ignore any extra frames, in either results or ground truth 23 | n = min(size(positions,1), size(ground_truth,1)); 24 | positions(n+1:end,:) = []; 25 | ground_truth(n+1:end,:) = []; 26 | end 27 | 28 | %calculate distances to ground truth over all frames 29 | distances = sqrt((positions(:,1) - ground_truth(:,1)).^2 + ... 30 | (positions(:,2) - ground_truth(:,2)).^2); 31 | distances(isnan(distances)) = []; 32 | 33 | %compute precisions 34 | for p = 1:max_threshold, 35 | precisions(p) = nnz(distances <= p) / numel(distances); 36 | end 37 | 38 | %plot the precisions 39 | if show == 1, 40 | figure('Number','off', 'Name',['Precisions - ' title]) 41 | plot(precisions, 'k-', 'LineWidth',2) 42 | xlabel('Threshold'), ylabel('Precision') 43 | end 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /tracking/getScalePatch.m: -------------------------------------------------------------------------------- 1 | function out = getScalePatch(img, pos, target_size, search_size, scale_window, scale_model_sz, hog_scale_cell_size) 2 | % KCC: Kernel Cross-Correlator 3 | % Visual Tracking Using KCC 4 | % 5 | % Copyright (C) 2017 6 | % Author: Wang Chen wang.chen@zoho.com Nanyang Technological University 7 | % Zhang Le zhang.le@adsc.com Advanced Digital Sciences Center 8 | % 9 | % This file is part of KCC. 10 | % 11 | % KCC is free software: you can redistribute it and/or modify 12 | % it under the terms of the GNU General Public License as published by 13 | % the Free Software Foundation, either version 3 of the License, or 14 | % (at your option) any later version. 15 | % 16 | % KCC is distributed in the hope that it will be useful, 17 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | % GNU General Public License for more details. 20 | % 21 | % You should have received a copy of the GNU General Public License 22 | % along with KCC. If not, see . 23 | 24 | padding=0; 25 | if size(img,3)>1 26 | img= single(rgb2gray(img))/255.0; 27 | end 28 | 29 | tmp_sz = floor((target_size * (1 + padding))*search_size); 30 | param0 = [pos(2), pos(1), tmp_sz(2)/target_size(2), 0,... 31 | tmp_sz(1)/target_size(2)/(target_size(1)/target_size(2)),0]; 32 | param0 = affparam2mat(param0); 33 | patch = warpimg(double(img), param0, target_size); 34 | patch = fhog(single(patch), hog_scale_cell_size); 35 | patch = patch(:,:,1:31); 36 | out = patch(:); 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /tracking/params.txt: -------------------------------------------------------------------------------- 1 | % configurable params (as in CVPR paper) 2 | params.hog_cell_size = 4; 3 | params.fixed_area = 150^2; % standard area to which we resize the target 4 | params.n_bins = 2^5; % number of bins for the color histograms (bg and fg models) 5 | params.learning_rate_pwp = 0.04; % bg and fg color models learning rate 6 | params.inner_padding = 0.2; % defines inner area used to sample colors from the foreground 7 | params.output_sigma_factor = 1/16 ; % standard deviation for the desired translation filter output 8 | params.lambda = 1e-3; 9 | params.lambda_scale = 0.1; % regularization weight 10 | params.learning_rate_cf = 0.01; % HOG model learning rate 11 | params.merge_factor = 0.3; % fixed interpolation factor - how to linearly combine the two responses 12 | params.learning_rate_scale = 0.008 %0.025; 13 | params.scale_sigma_factor = 1/16; 14 | params.scale_sigma = 0.1; 15 | params.num_scales = 11; 16 | params.scale_step = 1.03; 17 | 18 | % fixed setup 19 | params.hog_scale_cell_size = 4; % Default DSST=4 20 | params.scale_model_factor = 1.0; 21 | params.scale_model_max_area = 32*16; %32*16 22 | params.feature_type = 'fhog'; 23 | params.scale_adaptation = true; 24 | params.grayscale_sequence = false; % suppose that sequence is colour 25 | params.merge_method = 'const_factor'; 26 | params.den_per_channel = false; 27 | 28 | %% debugging stuff 29 | params.visualization = 0; % show output bbox on frame 30 | params.visualization_dbg = 0; % show also segmentation, desired response and filter output 31 | -------------------------------------------------------------------------------- /tracking/wrappers.hpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Piotr's Computer Vision Matlab Toolbox Version 3.00 3 | * Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] 4 | * Licensed under the Simplified BSD License [see external/bsd.txt] 5 | *******************************************************************************/ 6 | #ifndef _WRAPPERS_HPP_ 7 | #define _WRAPPERS_HPP_ 8 | #ifdef MATLAB_MEX_FILE 9 | 10 | // wrapper functions if compiling from Matlab 11 | #include "mex.h" 12 | inline void wrError(const char *errormsg) { mexErrMsgTxt(errormsg); } 13 | inline void* wrCalloc( size_t num, size_t size ) { return mxCalloc(num,size); } 14 | inline void* wrMalloc( size_t size ) { return mxMalloc(size); } 15 | inline void wrFree( void * ptr ) { mxFree(ptr); } 16 | 17 | #else 18 | 19 | // wrapper functions if compiling from C/C++ 20 | inline void wrError(const char *errormsg) { throw errormsg; } 21 | inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size); } 22 | inline void* wrMalloc( size_t size ) { return malloc(size); } 23 | inline void wrFree( void * ptr ) { free(ptr); } 24 | 25 | #endif 26 | 27 | // platform independent aligned memory allocation (see also alFree) 28 | void* alMalloc( size_t size, int alignment ) { 29 | const size_t pSize = sizeof(void*), a = alignment-1; 30 | void *raw = wrMalloc(size + a + pSize); 31 | void *aligned = (void*) (((size_t) raw + pSize + a) & ~a); 32 | *(void**) ((size_t) aligned-pSize) = raw; 33 | return aligned; 34 | } 35 | 36 | // platform independent alignned memory de-allocation (see also alMalloc) 37 | void alFree(void* aligned) { 38 | void* raw = *(void**)((char*)aligned-sizeof(void*)); 39 | wrFree(raw); 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /tracking/updateHistModel.m: -------------------------------------------------------------------------------- 1 | function [bg_hist_new, fg_hist_new] = updateHistModel(new_model, patch, bg_area, fg_area, target_sz, norm_area, n_bins, grayscale_sequence, bg_hist, fg_hist, learning_rate_pwp) 2 | %UPDATEHISTMODEL create new models for foreground and background or update the current ones 3 | 4 | % Get BG (frame around target_sz) and FG masks (inner portion of target_sz) 5 | pad_offset1 = (bg_area-target_sz)/2; % we constrained the difference to be mod2, so we do not have to round here 6 | % assert(sum(pad_offset1==round(pad_offset1))==2, 'difference between bg_area and target_sz has to be even.'); 7 | 8 | bg_mask = true(bg_area); % init bg_mask 9 | pad_offset1(pad_offset1<=0)=1; 10 | bg_mask(pad_offset1(1)+1:end-pad_offset1(1), pad_offset1(2)+1:end-pad_offset1(2)) = false; 11 | 12 | pad_offset2 = (bg_area-fg_area)/2; % we constrained the difference to be mod2, so we do not have to round here 13 | % assert(sum(pad_offset2==round(pad_offset2))==2, 'difference between bg_area and fg_area has to be even.'); 14 | fg_mask = false(bg_area); % init fg_mask 15 | pad_offset2(pad_offset2<=0)=1; 16 | fg_mask(pad_offset2(1)+1:end-pad_offset2(1), pad_offset2(2)+1:end-pad_offset2(2)) = true; 17 | 18 | fg_mask = mexResize(fg_mask, norm_area, 'auto'); 19 | bg_mask = mexResize(bg_mask, norm_area, 'auto'); 20 | 21 | %% (TRAIN) BUILD THE MODEL 22 | if new_model 23 | % from scratch (frame=1) 24 | bg_hist_new = computeHistogram(patch, bg_mask, n_bins, grayscale_sequence); 25 | fg_hist_new = computeHistogram(patch, fg_mask, n_bins, grayscale_sequence); 26 | else 27 | % update the model 28 | bg_hist_new = (1 - learning_rate_pwp)*bg_hist + learning_rate_pwp*computeHistogram(patch, bg_mask, n_bins, grayscale_sequence); 29 | fg_hist_new = (1 - learning_rate_pwp)*fg_hist + learning_rate_pwp*computeHistogram(patch, fg_mask, n_bins, grayscale_sequence); 30 | end 31 | 32 | end -------------------------------------------------------------------------------- /tracking/getScaleSubwindow_v1.m: -------------------------------------------------------------------------------- 1 | function out = getScaleSubwindow_v1(img, pos, target_size, search_size, scale_window, scale_model_sz, hog_scale_cell_size) 2 | % KCC: Kernel Cross-Correlator 3 | % Visual Tracking Using KCC 4 | % 5 | % Copyright (C) 2017 6 | % Author: Wang Chen wang.chen@zoho.com Nanyang Technological University 7 | % Zhang Le zhang.le@adsc.com Advanced Digital Sciences Center 8 | % 9 | % This file is part of KCC. 10 | % 11 | % KCC is free software: you can redistribute it and/or modify 12 | % it under the terms of the GNU General Public License as published by 13 | % the Free Software Foundation, either version 3 of the License, or 14 | % (at your option) any later version. 15 | % 16 | % KCC is distributed in the hope that it will be useful, 17 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | % GNU General Public License for more details. 20 | % 21 | % You should have received a copy of the GNU General Public License 22 | % along with KCC. If not, see . 23 | padding=0; 24 | num_scales = length(search_size); 25 | if size(img,3)>1 26 | img= single(rgb2gray(img))/255.0; 27 | end 28 | for s = 1:num_scales 29 | tmp_sz = floor((target_size * (1 + padding))*search_size(s)); 30 | param0 = [pos(2), pos(1), tmp_sz(2)/target_size(2), 0,... 31 | tmp_sz(1)/target_size(2)/(target_size(1)/target_size(2)),0]; 32 | param0 = affparam2mat(param0); 33 | patch = warpimg(double(img), param0, target_size); 34 | patch = fhog(single(patch), hog_scale_cell_size); 35 | patch = patch(:,:,1:31); 36 | 37 | if s == 1 38 | out = zeros(numel(patch), num_scales, 'single'); 39 | end 40 | 41 | % window 42 | out(:,s) = patch(:);%* scale_window(s); 43 | end 44 | 45 | -------------------------------------------------------------------------------- /tracking/get_feature_map.m: -------------------------------------------------------------------------------- 1 | function out = get_feature_map(im_patch, features, w2c) 2 | 3 | % out = get_feature_map(im_patch, features, w2c) 4 | % 5 | % Extracts the given features from the image patch. w2c is the 6 | % Color Names matrix, if used. 7 | 8 | if nargin < 3 9 | w2c = []; 10 | end 11 | 12 | % the names of the features that can be used 13 | valid_features = {'gray', 'cn'}; 14 | 15 | % the dimension of the valid features 16 | feature_levels = [1 10]'; 17 | 18 | num_valid_features = length(valid_features); 19 | used_features = false(num_valid_features, 1); 20 | 21 | % get the used features 22 | for i = 1:num_valid_features 23 | used_features(i) = any(strcmpi(valid_features{i}, features)); 24 | end 25 | 26 | % total number of used feature levels 27 | num_feature_levels = sum(feature_levels .* used_features); 28 | 29 | level = 0; 30 | 31 | % If grayscale image 32 | if size(im_patch, 3) == 1 33 | % Features that are available for grayscale sequances 34 | 35 | % Grayscale values (image intensity) 36 | out = single(im_patch)/255 - 0.5; 37 | else 38 | % Features that are available for color sequances 39 | 40 | % allocate space (for speed) 41 | out = zeros(size(im_patch, 1), size(im_patch, 2), num_feature_levels, 'single'); 42 | 43 | % Grayscale values (image intensity) 44 | if used_features(1) 45 | out(:,:,level+1) = single(rgb2gray(im_patch))/255 - 0.5; 46 | level = level + feature_levels(1); 47 | end 48 | 49 | % Color Names 50 | if used_features(2) 51 | if isempty(w2c) 52 | % load the RGB to color name matrix if not in input 53 | temp = load('w2crs'); 54 | w2c = temp.w2crs; 55 | end 56 | 57 | % extract color descriptor 58 | out(:,:,level+(1:10)) = im2c(single(im_patch), w2c, -2); 59 | level = level + feature_levels(2); 60 | end 61 | end -------------------------------------------------------------------------------- /recognition/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | WARD1.0 103 | *.asv 104 | data.mat 105 | results.mat 106 | performances.mat 107 | *.mat -------------------------------------------------------------------------------- /recognition/show_example.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | load('data.mat'); 19 | %% show 20 | sequence = 100:200; 21 | subject = 1; 22 | activity = 1; 23 | samples =1; 24 | 25 | 26 | example1 = data{1, 1, 1}(sequence, :)'; 27 | example2 = data{1, 8, 1}(sequence, :)'; 28 | example3 = data{1, 9, 1}(sequence, :)'; 29 | 30 | 31 | figure(1); 32 | subplot(211); 33 | grid off; 34 | imagesc(example1); 35 | axis equal; 36 | title ('The color map of activity ''ReSt'' from the first subject') 37 | colormap('jet') 38 | axis([1,100,1,25]); 39 | colorbar; 40 | 41 | subplot(212); 42 | grid off; 43 | imagesc(example2); 44 | axis equal; 45 | title ('The color map of activity ''TuRi'' from the first subject') 46 | colormap('jet') 47 | axis([1,100,1,25]); 48 | colorbar; 49 | 50 | figure (2) 51 | subplot(311); 52 | grid off; 53 | imagesc(example1); 54 | axis equal; 55 | title ('The color map of activity ''ReSt'' from the first subject') 56 | colormap('jet') 57 | axis([1,100,1,25]); 58 | colorbar; 59 | 60 | subplot(312); 61 | grid off; 62 | imagesc(example2); 63 | axis equal; 64 | title ('The color map of activity ''TuRi'' from the first subject') 65 | colormap('jet') 66 | axis([1,100,1,25]); 67 | colorbar; 68 | 69 | subplot(313); 70 | grid off; 71 | imagesc(example3); 72 | axis equal; 73 | title ('The color map of activity ''Up'' from the first subject') 74 | colormap('jet') 75 | axis([1,100,1,25]); 76 | colorbar; -------------------------------------------------------------------------------- /tracking/getScaleSubwindow.m: -------------------------------------------------------------------------------- 1 | function out = getScaleSubwindow(im, pos, base_target_sz, scale_factors, scale_window, scale_model_sz, hog_scale_cell_size) 2 | 3 | % KCC: Kernel Cross-Correlator 4 | % Visual Tracking Using KCC 5 | % 6 | % Copyright (C) 2017 7 | % Author: Wang Chen wang.chen@zoho.com Nanyang Technological University 8 | % Zhang Le zhang.le@adsc.com Advanced Digital Sciences Center 9 | % 10 | % This file is part of KCC. 11 | % 12 | % KCC is free software: you can redistribute it and/or modify 13 | % it under the terms of the GNU General Public License as published by 14 | % the Free Software Foundation, either version 3 of the License, or 15 | % (at your option) any later version. 16 | % 17 | % KCC is distributed in the hope that it will be useful, 18 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | % GNU General Public License for more details. 21 | % 22 | % You should have received a copy of the GNU General Public License 23 | % along with KCC. If not, see . 24 | num_scales = length(scale_factors); 25 | 26 | for s = 1:num_scales 27 | patch_sz = floor(base_target_sz * scale_factors(s)); 28 | %make sure the size is not to small 29 | patch_sz = max(patch_sz, 2); 30 | 31 | xs = floor(pos(2)) + (1:patch_sz(2)) - floor(patch_sz(2)/2); 32 | ys = floor(pos(1)) + (1:patch_sz(1)) - floor(patch_sz(1)/2); 33 | 34 | %check for out-of-bounds coordinates, and set them to the values at 35 | %the borders 36 | xs(xs < 1) = 1; 37 | ys(ys < 1) = 1; 38 | xs(xs > size(im,2)) = size(im,2); 39 | ys(ys > size(im,1)) = size(im,1); 40 | 41 | %extract image 42 | im_patch = im(ys, xs, :); 43 | 44 | % resize image to model size 45 | im_patch_resized = mexResize(im_patch, scale_model_sz, 'auto'); 46 | 47 | % extract scale features 48 | temp_hog = fhog(single(im_patch_resized), hog_scale_cell_size); 49 | temp = temp_hog(:,:,1:31); 50 | 51 | if s == 1 52 | out = zeros(numel(temp), num_scales, 'single'); 53 | end 54 | 55 | % window 56 | out(:,s) = temp(:) * scale_window(s); 57 | end 58 | -------------------------------------------------------------------------------- /tracking/run_KCC.m: -------------------------------------------------------------------------------- 1 | function results = run_KCC(seq, res_path, bSaveImage) 2 | % KCC: Kernel Cross-Correlator 3 | % Visual Tracking Using KCC 4 | % 5 | % Copyright (C) 2017 6 | % Author: Wang Chen wang.chen@zoho.com Nanyang Technological University 7 | % Zhang Le zhang.le@adsc.com Advanced Digital Sciences Center 8 | % 9 | % This file is part of KCC. 10 | % 11 | % KCC is free software: you can redistribute it and/or modify 12 | % it under the terms of the GNU General Public License as published by 13 | % the Free Software Foundation, either version 3 of the License, or 14 | % (at your option) any later version. 15 | % 16 | % KCC is distributed in the hope that it will be useful, 17 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | % GNU General Public License for more details. 20 | % 21 | % You should have received a copy of the GNU General Public License 22 | % along with KCC. If not, see . 23 | 24 | %% Read params.txt 25 | params = readParams('params.txt'); 26 | params.img_files = seq.s_frames; 27 | params.img_path = ''; 28 | 29 | im = imread(params.img_files{1}); 30 | % grayscale sequence? --> use 1D instead of 3D histograms 31 | if(size(im,3)==1) 32 | params.grayscale_sequence = true; 33 | end 34 | 35 | region = seq.init_rect; 36 | 37 | if(numel(region)==8) 38 | % polygon format (VOT14, VOT15) 39 | [cx, cy, w, h] = getAxisAlignedBB(region); 40 | else % rectangle format (WuCVPR13) 41 | x = region(1); 42 | y = region(2); 43 | w = region(3); 44 | h = region(4); 45 | cx = x+w/2; 46 | cy = y+h/2; 47 | end 48 | 49 | % init_pos is the centre of the initial bounding box 50 | params.init_pos = [cy cx]; 51 | params.target_sz = round([h w]); 52 | 53 | [params, bg_area, fg_area, area_resize_factor] = initializeAllAreas(im, params); 54 | 55 | % in runTracker we do not output anything because it is just for debug 56 | params.fout = -1; 57 | 58 | % start the actual tracking 59 | results = trackerMain_otb_wangchen(params, im, bg_area, fg_area, area_resize_factor); 60 | fclose('all'); 61 | end -------------------------------------------------------------------------------- /tracking/initializeAllAreas.m: -------------------------------------------------------------------------------- 1 | function [params, bg_area, fg_area, area_resize_factor] = initializeAllAreas(im, params) 2 | 3 | % we want a regular frame surrounding the object 4 | avg_dim = sum(params.target_sz)/2; 5 | % size from which we extract features 6 | bg_area = round(params.target_sz + avg_dim); 7 | % pick a "safe" region smaller than bbox to avoid mislabeling 8 | fg_area = round(params.target_sz - avg_dim * params.inner_padding); 9 | % saturate to image size 10 | if(bg_area(2)>size(im,2)), bg_area(2)=size(im,2)-1; end 11 | if(bg_area(1)>size(im,1)), bg_area(1)=size(im,1)-1; end 12 | % make sure the differences are a multiple of 2 (makes things easier later in color histograms) 13 | bg_area = bg_area - mod(bg_area - params.target_sz, 2); 14 | fg_area = fg_area + mod(bg_area - fg_area, 2); 15 | 16 | % Compute the rectangle with (or close to) params.fixedArea and 17 | % same aspect ratio as the target bbox 18 | area_resize_factor = sqrt(params.fixed_area/prod(bg_area)); 19 | params.norm_bg_area = round(bg_area * area_resize_factor); 20 | % Correlation Filter (HOG) feature space 21 | % It smaller that the norm bg area if HOG cell size is > 1 22 | params.cf_response_size = floor(params.norm_bg_area / params.hog_cell_size); 23 | % given the norm BG area, which is the corresponding target w and h? 24 | norm_target_sz_w = 0.75*params.norm_bg_area(2) - 0.25*params.norm_bg_area(1); 25 | norm_target_sz_h = 0.75*params.norm_bg_area(1) - 0.25*params.norm_bg_area(2); 26 | % norm_target_sz_w = params.target_sz(2) * params.norm_bg_area(2) / bg_area(2); 27 | % norm_target_sz_h = params.target_sz(1) * params.norm_bg_area(1) / bg_area(1); 28 | params.norm_target_sz = round([norm_target_sz_h norm_target_sz_w]); 29 | % distance (on one side) between target and bg area 30 | norm_pad = floor((params.norm_bg_area - params.norm_target_sz) / 2); 31 | radius = min(norm_pad); 32 | % norm_delta_area is the number of rectangles that are considered. 33 | % it is the "sampling space" and the dimension of the final merged resposne 34 | % it is squared to not privilege any particular direction 35 | params.norm_delta_area = (2*radius+1) * [1, 1]; 36 | % Rectangle in which the integral images are computed. 37 | % Grid of rectangles ( each of size norm_target_sz) has size norm_delta_area. 38 | params.norm_pwp_search_area = params.norm_target_sz + params.norm_delta_area - 1; 39 | 40 | end 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kernel Cross-Correlator (KCC) 2 | 3 | This repo contains source codes for the following paper [(PDF available here)](https://arxiv.org/pdf/1709.05936.pdf), which is accepted by AAAI-18: 4 | 5 | [Chen Wang](http://wangchen.online), [Le Zhang](https://sites.google.com/site/zhangleuestc/home), [Lihua Xie](http://www.ntu.edu.sg/home/elhxie/), [Junsong Yuan](http://www.ntu.edu.sg/home/jsyuan/), Kernel Cross-Correlator, In AAAI Conference on Artificial Intelligence (AAAI-18), pages 4179-4186. Feb. 2018 6 | 7 | There are two experiments in the paper, i.e. visual tracking, human activity recognition using wearable devices, which are contained in the independent folders, respectively. 8 | 9 | 10 | You may find instructions to run the codes for visual tracking: 11 | 12 | https://github.com/wang-chen/KCC/blob/master/tracking/README.md 13 | 14 | 15 | You may find instructions to run the codes for human activity recognition using wearable devices: 16 | 17 | https://github.com/wang-chen/KCC/blob/master/recognition/README.md 18 | 19 | 20 | If you find this repo is useful for your projects, you may cite it as: 21 | 22 | @inproceedings{wang2018kernel, 23 | title={{Kernel Cross-Correlator}}, 24 | author={Wang, Chen and Zhang, Le and Xie, Lihua and Yuan, Junsong}, 25 | booktitle={AAAI Conference on Artificial Intelligence (AAAI-18)}, 26 | year={2018}, 27 | pages= {4179-4186}, 28 | mon=feb 29 | } 30 | 31 | # Works or papers using KCC: 32 | 33 | [Chen Wang](https://wang-chen.github.io) *, Tete Ji *, Thien-Minh Nguyen, and [Lihua Xie](http://www.ntu.edu.sg/home/elhxie/), "Correlation Flow: Robust Optical Flow Using Kernel Cross-Correlators", IEEE International Conference on Robotics and Automation (ICRA), May. 2018. ([Codes available here](https://github.com/wang-chen/correlation_flow))([PDF available here](https://arxiv.org/pdf/1802.07078.pdf)) 34 | 35 | 36 | Thien-Minh Nguyen, Abdul Hanif Zaini, [Chen Wang](https://wang-chen.github.io) , Kexin Guo, and [Lihua Xie](http://www.ntu.edu.sg/home/elhxie/), "Robust Target-relative Localization with Ultra-Wideband Ranging and Communication", IEEE International Conference on Robotics and Automation (ICRA), May. 2018. ([Video available here](https://youtu.be/ZkxFDGdB0hQ)) 37 | 38 | [Chen Wang](https://wang-chen.github.io), Minh-Chung Hoang, [Lihua Xie](http://www.ntu.edu.sg/home/elhxie/), and [Junsong Yuan](http://www.ntu.edu.sg/home/jsyuan/), "Non-Iterative RGB-D-inertial Odometry", arXiv preprint arXiv:1710.05502, 2017. ([PDF available here](https://arxiv.org/pdf/1710.05502.pdf)) 39 | -------------------------------------------------------------------------------- /recognition/data_conversion.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | clear; clc 19 | % You need to download the WARD dataset to current folder. 20 | % 21 | folder = './WARD1.0/'; 22 | addpath('./natsortfiles/') 23 | 24 | if ~(7==exist(folder,'dir')) 25 | url = 'https://people.eecs.berkeley.edu/~yang/software/WAR/WARD1.zip'; 26 | filename = 'WARD1.zip'; 27 | disp('Downloading database...') 28 | websave(filename,url); 29 | disp('Extracting files...') 30 | try 31 | unzip(filename, '.'); 32 | catch err 33 | disp('Unable to upzip, you may need to download/unzip the database to currently folder manually via link:') 34 | disp(url) 35 | return 36 | end 37 | disp('Extracted.') 38 | end 39 | 40 | if (7==exist(folder,'dir')) 41 | disp('Data Conversion...') 42 | else 43 | return 44 | end 45 | 46 | files = dir(folder); 47 | fileIndex = find([files.isdir]); 48 | fileIndex = fileIndex(3:end); 49 | files = files(fileIndex); 50 | data={}; 51 | 52 | files = natsortfiles({files(:).name}); 53 | 54 | for i = 1:length(files) 55 | subfolder = files(i); 56 | matfolders = dir(strcat(folder,subfolder{1})); 57 | matIndex = find(~[matfolders.isdir]); 58 | matfolders = matfolders(matIndex); 59 | matfolder_files = natsortfiles({matfolders(:).name}); 60 | 61 | for j = 1:length(matfolder_files) 62 | matfiles = matfolder_files(j); 63 | filename = strcat(folder, subfolder,'/',matfiles{1}); 64 | wd = load(filename{1}); 65 | reading=[]; 66 | for k=1:5 67 | col = wd.WearableData.Reading{k}; 68 | col(isinf (col))=0; 69 | col(isnan (col))=0; 70 | tran = col-mean(col); 71 | reading = [reading, tran./2./max(abs(tran))+0.5]; 72 | reading(isnan(reading))=0; 73 | end 74 | number = sscanf(filename{1},'./WARD1.0/Subject%d/a%dt%d.mat'); 75 | data{number(1),number(2), number(3)} = reading; 76 | % data{i,j}.name = filename; 77 | end 78 | end 79 | 80 | save('data.mat', 'data'); 81 | disp('Done. Saved to data.mat') 82 | clear 83 | -------------------------------------------------------------------------------- /tracking/fhog.m: -------------------------------------------------------------------------------- 1 | function H = fhog( I, binSize, nOrients, clip, crop ) 2 | % Efficiently compute Felzenszwalb's HOG (FHOG) features. 3 | % 4 | % A fast implementation of the HOG variant used by Felzenszwalb et al. 5 | % in their work on discriminatively trained deformable part models. 6 | % http://www.cs.berkeley.edu/~rbg/latent/index.html 7 | % Gives nearly identical results to features.cc in code release version 5 8 | % but runs 4x faster (over 125 fps on VGA color images). 9 | % 10 | % The computed HOG features are 3*nOrients+5 dimensional. There are 11 | % 2*nOrients contrast sensitive orientation channels, nOrients contrast 12 | % insensitive orientation channels, 4 texture channels and 1 all zeros 13 | % channel (used as a 'truncation' feature). Using the standard value of 14 | % nOrients=9 gives a 32 dimensional feature vector at each cell. This 15 | % variant of HOG, refered to as FHOG, has been shown to achieve superior 16 | % performance to the original HOG features. For details please refer to 17 | % work by Felzenszwalb et al. (see link above). 18 | % 19 | % This function is essentially a wrapper for calls to gradientMag() 20 | % and gradientHist(). Specifically, it is equivalent to the following: 21 | % [M,O] = gradientMag( I,0,0,0,1 ); softBin = -1; useHog = 2; 22 | % H = gradientHist(M,O,binSize,nOrients,softBin,useHog,clip); 23 | % See gradientHist() for more general usage. 24 | % 25 | % This code requires SSE2 to compile and run (most modern Intel and AMD 26 | % processors support SSE2). Please see: http://en.wikipedia.org/wiki/SSE2. 27 | % 28 | % USAGE 29 | % H = fhog( I, [binSize], [nOrients], [clip], [crop] ) 30 | % 31 | % INPUTS 32 | % I - [hxw] color or grayscale input image (must have type single) 33 | % binSize - [8] spatial bin size 34 | % nOrients - [9] number of orientation bins 35 | % clip - [.2] value at which to clip histogram bins 36 | % crop - [0] if true crop boundaries 37 | % 38 | % OUTPUTS 39 | % H - [h/binSize w/binSize nOrients*3+5] computed hog features 40 | % 41 | % EXAMPLE 42 | % I=imResample(single(imread('peppers.png'))/255,[480 640]); 43 | % tic, for i=1:100, H=fhog(I,8,9); end; disp(100/toc) % >125 fps 44 | % figure(1); im(I); V=hogDraw(H,25,1); figure(2); im(V) 45 | % 46 | % EXAMPLE 47 | % % comparison to features.cc (requires DPM code release version 5) 48 | % I=imResample(single(imread('peppers.png'))/255,[480 640]); Id=double(I); 49 | % tic, for i=1:100, H1=features(Id,8); end; disp(100/toc) 50 | % tic, for i=1:100, H2=fhog(I,8,9,.2,1); end; disp(100/toc) 51 | % figure(1); montage2(H1); figure(2); montage2(H2); 52 | % D=abs(H1-H2); mean(D(:)) 53 | % 54 | % See also hog, hogDraw, gradientHist 55 | % 56 | % Piotr's Image&Video Toolbox Version 3.23 57 | % Copyright 2013 Piotr Dollar. [pdollar-at-caltech.edu] 58 | % Please email me if you find bugs, or have suggestions or questions! 59 | % Licensed under the Simplified BSD License [see external/bsd.txt] 60 | 61 | %Note: modified to be more self-contained 62 | 63 | if( nargin<2 ), binSize=8; end 64 | if( nargin<3 ), nOrients=9; end 65 | if( nargin<4 ), clip=.2; end 66 | if( nargin<5 ), crop=0; end 67 | 68 | softBin = -1; useHog = 2; b = binSize; 69 | 70 | [M,O]=gradientMex('gradientMag',I,0,1); 71 | 72 | H = gradientMex('gradientHist',M,O,binSize,nOrients,softBin,useHog,clip); 73 | 74 | if( crop ), e=mod(size(I),b). 16 | 17 | function results = activity_recognition(lambda, sigma) 18 | close all 19 | load('data.mat'); 20 | 21 | if nargin < 2 22 | lambda = 0.0015; 23 | sigma = 1; 24 | end 25 | 26 | disp('running recognition...') 27 | sequence = 76:125; % remove first 75 unstable points, cannot be larger, or Index exceeds matrix dimensions 28 | time_kcc = zeros(13,1); 29 | time_dtw = zeros(13,1); 30 | 31 | %% examples 32 | for subject = 1:size(data,1) 33 | for activity = 1:size(data, 2) 34 | for samples = 1:5%size(data, 3) %only one subject has the 6th sample in only one activity 35 | if isempty(data{subject, activity, samples}) 36 | continue; 37 | end 38 | 39 | train = data{subject, activity, samples}(sequence, :); 40 | tic 41 | correlator = kcc_train(train, lambda, sigma); 42 | time_kcc(activity) = time_kcc(activity) + toc; 43 | 44 | for activity_test = 1:size(data, 2) 45 | for samples_test = 1:5%size(data, 3) %only one subject has the 6th sample in only one activity 46 | if isempty(data{subject, activity_test, samples_test}) 47 | continue; 48 | end 49 | 50 | test = data{subject, activity_test, samples_test}(sequence, :); 51 | 52 | tic 53 | response(subject, 5*(activity-1)+ samples, 5*(activity_test-1)+ samples_test) = kcc(test, correlator); 54 | time_kcc(activity_test) = time_kcc(activity_test) + toc; 55 | 56 | tic 57 | distance(subject, 5*(activity-1)+ samples, 5*(activity_test-1)+ samples_test) = dtw(train', test'); 58 | time_dtw(activity_test) = time_dtw(activity_test) + toc; 59 | end 60 | end 61 | end 62 | end 63 | end 64 | 65 | time_use = [time_kcc, time_dtw]; 66 | filename = 'results.mat'; 67 | save(filename, 'response', 'distance', 'time_use'); 68 | disp('Saved results to results.mat') 69 | [accuracy_kcc, accuracy_dtw] = show_results(); 70 | results = [accuracy_dtw, accuracy_kcc, sum(time_dtw), sum(time_kcc), sigma, lambda]; 71 | fprintf('accuracy_dtw: %f; accuracy_kcc: %f; time_dtw: %f s, time_kcc: %f s; sigma: %f lambda: %f\n', ... 72 | results(1), results(2), results(3), results(4), results(5), results(6)); 73 | disp('Done.') 74 | end 75 | -------------------------------------------------------------------------------- /tracking/unfreezeColors.m: -------------------------------------------------------------------------------- 1 | function unfreezeColors(h) 2 | % unfreezeColors Restore colors of a plot to original indexed color. (v2.3) 3 | % 4 | % Useful if you want to apply a new colormap to plots whose 5 | % colors were previously frozen with freezeColors. 6 | % 7 | % Usage: 8 | % unfreezeColors unfreezes all objects in current axis, 9 | % unfreezeColors(axh) same, but works on axis axh. axh can be vector. 10 | % unfreezeColors(figh) same, but for all objects in figure figh. 11 | % 12 | % Has no effect on objects on which freezeColors was not already called. 13 | % (Note: if colorbars were frozen using cbfreeze, use cbfreeze('off') to 14 | % unfreeze them. See freezeColors for information on cbfreeze.) 15 | % 16 | % 17 | % See also freezeColors, freezeColors_pub.html, cbfreeze. 18 | % 19 | % 20 | % John Iversen (iversen@nsi.edu) 3/23/05 21 | % 22 | 23 | % Changes: 24 | % JRI 9/1/06 now restores any object with frozen CData; 25 | % can unfreeze an entire figure at once. 26 | % JRI 4/7/10 Change documentation for colorbars 27 | 28 | % Free for all uses, but please retain the following: 29 | % 30 | % Original Author: 31 | % John Iversen, 2005-10 32 | % john_iversen@post.harvard.edu 33 | 34 | error(nargchk(0,1,nargin,'struct')) 35 | 36 | appdatacode = 'JRI__freezeColorsData'; 37 | 38 | %default: operate on gca 39 | if nargin < 1, 40 | h = gca; 41 | end 42 | 43 | if ~ishandle(h), 44 | error('JRI:unfreezeColors:invalidHandle',... 45 | 'The argument must be a valid graphics handle to a figure or axis') 46 | end 47 | 48 | %if h is a figure, loop on its axes 49 | if strcmp(get(h,'type'),'figure'), 50 | h = get(h,'children'); 51 | end 52 | 53 | for h1 = h', %loop on axes 54 | 55 | %process all children, acting only on those with saved CData 56 | % ( in appdata JRI__freezeColorsData) 57 | ch = findobj(h1); 58 | 59 | for hh = ch', 60 | 61 | %some object handles may be invalidated when their parent changes 62 | % (e.g. restoring colors of a scattergroup unfortunately changes 63 | % the handles of all its children). So, first check to make sure 64 | % it's a valid handle 65 | if ishandle(hh) 66 | if isappdata(hh,appdatacode), 67 | ad = getappdata(hh,appdatacode); 68 | %get oroginal cdata 69 | %patches have to be handled separately (see note in freezeColors) 70 | if ~strcmp(get(hh,'type'),'patch'), 71 | cdata = get(hh,'CData'); 72 | else 73 | cdata = get(hh,'faceVertexCData'); 74 | cdata = permute(cdata,[1 3 2]); 75 | end 76 | indexed = ad{1}; 77 | scalemode = ad{2}; 78 | 79 | %size consistency check 80 | if all(size(indexed) == size(cdata(:,:,1))), 81 | %ok, restore indexed cdata 82 | if ~strcmp(get(hh,'type'),'patch'), 83 | set(hh,'CData',indexed); 84 | else 85 | set(hh,'faceVertexCData',indexed); 86 | end 87 | %restore cdatamapping, if needed 88 | g = get(hh); 89 | if isfield(g,'CDataMapping'), 90 | set(hh,'CDataMapping',scalemode); 91 | end 92 | %clear appdata 93 | rmappdata(hh,appdatacode) 94 | else 95 | warning('JRI:unfreezeColors:internalCdataInconsistency',... 96 | ['Could not restore indexed data: it is the wrong size. ' ... 97 | 'Were the axis contents changed since the call to freezeColors?']) 98 | end 99 | 100 | end %test if has our appdata 101 | end %test ishandle 102 | 103 | end %loop on children 104 | 105 | end %loop on axes 106 | 107 | -------------------------------------------------------------------------------- /recognition/show_results.m: -------------------------------------------------------------------------------- 1 | % KCC: Kernel Cross-Correlator 2 | % Activity Recognition Using KCC 3 | % 4 | % Copyright (C) 2017 Wang Chen wang.chen@zoho.com 5 | % Nanyang Technological University 6 | % This program is free software: you can redistribute it and/or modify 7 | % it under the terms of the GNU General Public License as published by 8 | % the Free Software Foundation, either version 3 of the License, or 9 | % (at your option) any later version. 10 | % This program is distributed in the hope that it will be useful, 11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | % GNU General Public License for more details. 14 | % You should have received a copy of the GNU General Public License 15 | % along with this program. If not, see . 16 | 17 | 18 | function [accuracy_kcc, accuracy_dtw] = show_results(filename) 19 | addpath('matrix2latex') 20 | if nargin < 1 21 | clear 22 | results = load('results.mat'); 23 | else 24 | load(filename); 25 | end 26 | 27 | fusion_matrix_kcc = zeros(65); 28 | fusion_matrix_dtw = zeros(65); 29 | 30 | response = results.response; 31 | distance = results.distance; 32 | 33 | %% show 34 | for s = 1:size(response,1) 35 | r = reshape(response(s,:,:),65,65); 36 | d = reshape(distance(s,:,:),65,65); 37 | if nargin < 1 38 | figure(1); 39 | subplot(4,5,s); 40 | 41 | imagesc(r./max(r(:))) 42 | axis off; 43 | axis equal; 44 | grid off; 45 | colorbar; 46 | 47 | figure(2); 48 | subplot(4,5,s); 49 | 50 | imagesc(d./max(d(:))); 51 | axis off; 52 | axis equal; 53 | grid off; 54 | colorbar; 55 | end 56 | 57 | r(eye(size(r))~=0)=0; 58 | [minvalue, idr] = max(r); 59 | d(d==0)=inf; 60 | [maxvalue, idd] = min(d); 61 | 62 | idx_kcc = sub2ind(size(fusion_matrix_kcc), 1:65, idr); 63 | fusion_matrix_kcc(idx_kcc) = fusion_matrix_kcc(idx_kcc) +1; 64 | 65 | idx_dtw = sub2ind(size(fusion_matrix_dtw), 1:65, idd); 66 | fusion_matrix_dtw(idx_dtw) = fusion_matrix_dtw(idx_dtw) +1; 67 | end 68 | 69 | fusion_matrix_kcc(eye(size(fusion_matrix_kcc))~=0) = size(response,1); 70 | fusion_matrix_dtw(eye(size(fusion_matrix_dtw))~=0) = size(distance,1); 71 | if nargin < 1 72 | figure(3); 73 | subplot(121); 74 | imagesc(fusion_matrix_kcc./size(response,1)); 75 | axis equal; 76 | axis([1,65,1,65]); 77 | colorbar; 78 | grid off; 79 | title('KCC'); 80 | subplot(122); 81 | imagesc(fusion_matrix_dtw./size(distance,1)); 82 | axis equal; 83 | colorbar; 84 | axis([1,65,1,65]); 85 | grid off; 86 | title('DTW'); 87 | end 88 | accuracy_kcc = trace(sum_blocks(fusion_matrix_kcc, 5, 5))/sum(fusion_matrix_kcc(:)); 89 | accuracy_dtw = trace(sum_blocks(fusion_matrix_dtw, 5, 5))/sum(fusion_matrix_dtw(:)); 90 | 91 | if nargin < 1 92 | fprintf('accuracy kcc: %f; dtw: %f\n', accuracy_kcc, accuracy_dtw); 93 | end 94 | 95 | table_comparison = ... 96 | [diag(sum_blocks(fusion_matrix_kcc, 5, 5)./200)*100,... 97 | diag(sum_blocks(fusion_matrix_dtw, 5, 5)./200)*100, results.time_use/65/65*1000*1000]; 98 | 99 | table_comparison = [table_comparison; mean(table_comparison)]; 100 | 101 | matrix2latex(table_comparison, 'comparison_results.txt'); 102 | % disp('Saved results table to Latex codes into comarison_results.txt') 103 | 104 | function out = sum_blocks(A, block_nrows, block_ncols) 105 | out = squeeze(sum(reshape(sum(reshape(A,block_nrows,[])),... 106 | size(A,1)/block_nrows,block_ncols,[]),2)); 107 | end 108 | end -------------------------------------------------------------------------------- /tracking/utility/interp2.cpp: -------------------------------------------------------------------------------- 1 | // interp2.cpp 2 | // 3 | // Copyright (C) Jongwoo Lim. 4 | // All rights reserved. 5 | // 6 | ////////////////////////////////////////////////////////////////////// 7 | 8 | #include "mex.h" 9 | #include 10 | 11 | //#include "cvbase/cvimage.h" 12 | 13 | #define ARR(A,r,c,nr,nc) (((r)<0 || (r)>=(nr) || (c)<0 || (c)>=(nc))? 0 : (A)[(c)*(nr)+(r)]) 14 | 15 | inline double interp(double *img, int w, int h, double x, double y) 16 | { 17 | register int x0 = (int) x, y0 = (int) y, x1 = x0+1, y1 = y0+1; 18 | register double rx0 = x-x0, rx1 = 1-rx0, ry = y-y0; 19 | return ((rx1*ARR(img,y0,x0,h,w) + rx0*ARR(img,y0,x1,h,w))*(1-ry) + 20 | (rx1*ARR(img,y1,x0,h,w) + rx0*ARR(img,y1,x1,h,w))*ry); 21 | } 22 | 23 | //----------------------------------------------------------------------------- 24 | 25 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 26 | { 27 | // check inputs 28 | if (nrhs < 3 || nrhs > 6) 29 | mexErrMsgTxt("invalid number of inputs: [x,y,]z,xi,yi[,method]"); 30 | if (nlhs != 1) 31 | mexErrMsgTxt("invalid number of outputs: zi"); 32 | 33 | const char *_argin[] = { "x","y","z","xi","yi","method" }; 34 | const char **argin = (nrhs < 4)? &_argin[2] : _argin; 35 | char buf[1024]; 36 | 37 | // Check input data 38 | const mxArray *X = NULL, *Y = NULL, *Z, *XI, *YI; 39 | if (nrhs < 4) 40 | Z = prhs[0], XI = prhs[1], YI = prhs[2]; 41 | else 42 | X = prhs[0], Y = prhs[1], Z = prhs[2], XI = prhs[3], YI = prhs[4]; 43 | 44 | if (nrhs == 4 || nrhs == 6) 45 | nrhs--; // Ignore method 46 | 47 | for (int ri = 0; ri < nrhs; ri++) { 48 | if (!prhs[ri]) 49 | { sprintf(buf,"invalid mxArray(%s)", argin[ri]); mexErrMsgTxt(buf); } 50 | if (!mxIsDouble(prhs[ri])) 51 | { sprintf(buf,"data must be double (%s)", argin[ri]); mexErrMsgTxt(buf); } 52 | } 53 | if (mxGetNumberOfDimensions(Z) != 2) 54 | mexErrMsgTxt("invalid Z dimension: should be 2"); 55 | // Need to check whether dims of X,Y,Z matche 56 | if (mxGetNumberOfElements(XI) != mxGetNumberOfElements(YI)) 57 | mexErrMsgTxt("XI and YI does not match"); 58 | 59 | // Build output data 60 | const int *dimz = mxGetDimensions(Z), *dim = mxGetDimensions(XI); 61 | int ndim = mxGetNumberOfDimensions(XI); 62 | 63 | register double dx = -1, dy = -1, sx = 1, sy = 1; 64 | if (nrhs >= 4) { 65 | int nx = mxGetNumberOfElements(X), ny = mxGetNumberOfElements(Y); 66 | double *pX = mxGetPr(X), *pY = mxGetPr(Y); 67 | if (nx == dimz[1] && ny == dimz[0]) 68 | dx = -pX[0], sx = (dimz[1]-1)/(pX[nx-1]-pX[0]), 69 | dy = -pY[0], sy = (dimz[0]-1)/(pY[ny-1]-pY[0]); 70 | else if (nx == ny && ny == mxGetNumberOfElements(Z)) 71 | dx = -pX[0], sx = (dimz[1]-1)/(pX[(dimz[1]-1)*dimz[0]]-pX[0]), 72 | dy = -pY[0], sy = (dimz[0]-1)/(pY[dimz[0]-1]-pY[0]); 73 | else 74 | mexErrMsgTxt("X and Y do not match with Z"); 75 | } 76 | if (mxIsComplex(Z)) { 77 | mxArray *ZI = plhs[0] = mxCreateNumericArray(ndim, dim, mxDOUBLE_CLASS, mxCOMPLEX); 78 | 79 | // Load input data and fill output array 80 | double *pZr = mxGetPr(Z), *pZi = mxGetPi(Z), *pXI = mxGetPr(XI), *pYI = mxGetPr(YI); 81 | double *pZIr = mxGetPr(ZI), *pZIi = mxGetPi(ZI); 82 | 83 | // cvImage imgr(pZr, dimz[0], dimz[1]), imgi(pZi, dimz[0], dimz[1]); 84 | int h = dimz[0], w = dimz[1]; 85 | for (int i = 0, n = mxGetNumberOfElements(XI); i < n; i++) { 86 | pZIr[i] = interp(pZr, w,h, sx*(pXI[i]+dx), sy*(pYI[i]+dy)); 87 | pZIi[i] = interp(pZi, w,h, sx*(pXI[i]+dx), sy*(pYI[i]+dy)); 88 | // cvtPoint p(sy*(pYI[i]+dy),sx*(pXI[i]+dx)); 89 | // pZIr[i] = imgr.interp(p); 90 | // pZIi[i] = imgi.interp(p); 91 | } 92 | } 93 | else { 94 | mxArray *ZI = plhs[0] = mxCreateNumericArray(ndim, dim, mxDOUBLE_CLASS, mxREAL); 95 | 96 | // Load input data and fill output array 97 | double *pZ = mxGetPr(Z), *pXI = mxGetPr(XI), *pYI = mxGetPr(YI); 98 | double *pZI = mxGetPr(ZI); 99 | 100 | // cvImage img(pZ, dimz[0], dimz[1]); 101 | int h = dimz[0], w = dimz[1]; 102 | for (int i = 0, n = mxGetNumberOfElements(XI); i < n; i++) { 103 | pZI[i] = interp(pZ, w,h, sx*(pXI[i]+dx), sy*(pYI[i]+dy)); 104 | // cvtPoint p(sy*(pYI[i]+dy),sx*(pXI[i]+dx)); 105 | // pZI[i] = img.interp(p); 106 | } 107 | } 108 | } 109 | 110 | //----------------------------------------------------------------------------- 111 | -------------------------------------------------------------------------------- /recognition/natsortfiles/natsortfiles_doc.m: -------------------------------------------------------------------------------- 1 | %% NATSORTFILES Examples 2 | % The function sorts a cell array of filenames or filepaths, taking into 4 | % account any number values within the strings. This is known as a "natural 5 | % order sort" or an "alphanumeric sort". Note that MATLAB's inbuilt 6 | % function 7 | % sorts the character codes only (as does |sort| in most programming languages). 8 | % 9 | % |NATSORTFILES| is not a naive natural-order sort, but sorts the filenames 10 | % and file extensions separately: this prevents the file extension separator 11 | % character |.| and file extension itself from influencing the sort order 12 | % of the complete filename+extension. Thus |NATSORTFILES| sorts shorter 13 | % filenames before longer ones, which is known as a "dictionary sort". 14 | % For the same reason filepaths are split at each path-separator 15 | % character, and each directory level is sorted separately. See the 16 | % "Explanation" sections below for more details. 17 | % 18 | % For sorting the rows of a cell array of strings use 19 | % . 20 | % 21 | % For sorting a cell array of strings use 22 | % . 23 | % 24 | %% Basic Usage: 25 | % By default |NATSORTFILES| interprets consecutive digits as being part of 26 | % a single integer, each number is considered to be as wide as one letter: 27 | A = {'a2.txt', 'a10.txt', 'a1.txt'}; 28 | sort(A) 29 | natsortfiles(A) 30 | %% Output 2: Sort Index 31 | % The second output argument is a numeric array of the sort indices |ndx|, 32 | % such that |Y = X(ndx)| where |Y = natsortfiles(X)|: 33 | [~,ndx] = natsortfiles(A) 34 | %% Example with DIR and a Cell Array 35 | % One common situation is using to identify files in a folder, sort them into the correct order, 37 | % and then loop over them: below is an example of how to do this. 38 | % Remember to all output arrays before the loop! 40 | D = 'natsortfiles_test'; % directory path 41 | S = dir(fullfile(D,'*.txt')); % get list of files in directory 42 | N = natsortfiles({S.name}); % sort file names into order 43 | for k = 1:numel(N) 44 | fullfile(D,N{k}) 45 | end 46 | %% Example with DIR and a Structure 47 | % Users who need to access the |DIR| structure fields can use |NATSORTFILE|'s 48 | % second output to sort |DIR|'s output structure into the correct order: 49 | D = 'natsortfiles_test'; % directory path 50 | S = dir(fullfile(D,'*.txt')); % get list of files in directory 51 | [~,ndx] = natsortfiles({S.name}); % indices of correct order 52 | S = S(ndx); % sort structure using indices 53 | for k = 1:numel(N) 54 | S(k).name; 55 | S(k).date; 56 | end 57 | %% Explanation: Dictionary Sort 58 | % Filenames and file extensions are separated by the extension separator, 59 | % the period character |.|, which gets sorted _after_ all of the characters 60 | % from 0 to 45, including |!"#$%&'()*+,-|, the space character, and all of 61 | % the control characters (newlines, tabs, etc). This means that a naive 62 | % sort or natural-order sort will sort some short filenames after longer 63 | % filenames. In order to provide the correct dictionary sort, with shorter 64 | % filenames first, |NATSORTFILES| sorts the filenames and file extensions 65 | % separately: 66 | B = {'test_ccc.m'; 'test-aaa.m'; 'test.m'; 'test.bbb.m'}; 67 | sort(B) % '-' sorts before '.' 68 | natsort(B) % '-' sorts before '.' 69 | natsortfiles(B) % correct dictionary sort 70 | %% Explanation: Filenames 71 | % |NATSORTFILES| combines a dictionary sort with a natural-order sort, so 72 | % that the number values within the filenames are taken into consideration: 73 | C = {'test2.m'; 'test10-old.m'; 'test.m'; 'test10.m'; 'test1.m'}; 74 | sort(C) % Wrong numeric order. 75 | natsort(C) % Correct numeric order, but longer before shorter. 76 | natsortfiles(C) % Correct numeric order and dictionary sort. 77 | %% Explanation: Filepaths 78 | % For the same reason, filepaths are split at each file path separator 79 | % character (both |/| and |\| are considered to be file path separators) 80 | % and every level of directory names are sorted separately. This ensures 81 | % that the directory names are sorted with a dictionary sort and that any 82 | % numbers are taken into consideration: 83 | D = {'A2-old\test.m';'A10\test.m';'A2\test.m';'AXarchive.zip';'A1\test.m'}; 84 | sort(D) % Wrong numeric order, and '-' sorts before '\': 85 | natsort(D) % correct numeric order, but longer before shorter. 86 | natsortfiles(D) % correct numeric order and dictionary sort. 87 | %% Regular Expression: Decimal Numbers, E-notation, +/- Sign. 88 | % |NATSORTFILES| is a wrapper for |NATSORT|, which means all of |NATSORT|'s 89 | % options are also supported. In particular the number recognition can be 90 | % customized to detect numbers with decimal digits, E-notation, a +/- sign, 91 | % or other specific features. This detection is defined by providing an 92 | % appropriate regular expression: see |NATSORT| for details and examples. 93 | E = {'test24.csv','test1.8.csv','test5.csv','test3.3.csv','test12.csv'}; 94 | natsortfiles(E,'\d+(\.\d+)?') -------------------------------------------------------------------------------- /recognition/natsortfiles/natsortfiles.m: -------------------------------------------------------------------------------- 1 | function [X,ndx] = natsortfiles(X,varargin) 2 | % Alphanumeric / Natural-Order sort of a cell array of filenames/filepaths. 3 | % 4 | % (c) 2017 Stephen Cobeldick 5 | % 6 | % Alphanumeric sort of a cell array of filenames or filepaths: sorts by 7 | % character order and also by the values of any numbers that are within 8 | % the strings. Filenames, file-extensions, and directories (if supplied) 9 | % are split apart and are sorted separately: this ensures that shorter 10 | % filenames sort before longer ones (i.e. just like a dictionary sort). 11 | % 12 | %%% Syntax: 13 | % Y = natsortfiles(X) 14 | % Y = natsortfiles(X,xpr) 15 | % Y = natsortfiles(X,xpr,) 16 | % [Y,ndx] = natsortfiles(X,...) 17 | % 18 | % To sort all of the strings in a cell array use NATSORT (File Exchange 34464). 19 | % To sort the rows of a cell array of strings use NATSORTROWS (File Exchange 47433). 20 | % 21 | % See also NATSORT NATSORTROWS SORT SORTROWS NUM2SIP NUM2BIP CELLSTR REGEXP DIR FILEPARTS FULLFILE FILESEP 22 | % 23 | %% File Dependency %% 24 | % 25 | % NATSORTFILES requires the function NATSORT (File Exchange 34464). The inputs 26 | % and are passed directly to NATSORT: see NATSORT for case 27 | % sensitivity, sort direction, numeric substring matching, and other options. 28 | % 29 | %% Explanation %% 30 | % 31 | % Using SORT on filenames will sort any of char(0:45), including the printing 32 | % characters ' !"#$%&''()*+,-', before the file extension separator character '.'. 33 | % Therefore this function splits the name and extension and sorts them separately. 34 | % 35 | % Similarly the file separator character within filepaths can cause longer 36 | % directory names to sort before shorter ones, as char(0:46)<'/' and char(0:91)<'\'. 37 | % NATSORTFILES splits filepaths at each file separator character and sorts 38 | % every level of the directory hierarchy separately, ensuring that shorter 39 | % directory names sort before longer, regardless of the characters in the names. 40 | % 41 | %% Examples %% 42 | % 43 | %%% DIR and Cell Array: 44 | % D = 'C:\Test'; 45 | % S = dir(fullfile(D,'*.txt')); 46 | % N = natsortfiles({S.name}); 47 | % for k = 1:numel(N) 48 | % fullfile(D,N{k}) 49 | % end 50 | % 51 | % A = {'a2.txt', 'a10.txt', 'a1.txt'}; 52 | % sort(A) % Wrong numeric order: 53 | % ans = 'a1.txt' 'a10.txt' 'a2.txt' 54 | % natsortfiles(A) 55 | % ans = 'a1.txt' 'a2.txt' 'a10.txt' 56 | % 57 | % B = {'test_new.m'; 'test-old.m'; 'test.m'}; 58 | % sort(B) % Note '-' sorts before '.': 59 | % ans = 60 | % 'test-old.m' 61 | % 'test.m' 62 | % 'test_new.m' 63 | % natsortfiles(B) % Shorter names before longer (dictionary sort): 64 | % ans = 65 | % 'test.m' 66 | % 'test-old.m' 67 | % 'test_new.m' 68 | % 69 | % C = {'test2.m'; 'test10-old.m'; 'test.m'; 'test10.m'; 'test1.m'}; 70 | % sort(C) % Wrong numeric order: 71 | % ans = 72 | % 'test.m' 73 | % 'test1.m' 74 | % 'test10-old.m' 75 | % 'test10.m' 76 | % 'test2.m' 77 | % natsortfiles(C) % Correct numeric order, shorter names before longer: 78 | % ans = 79 | % 'test.m' 80 | % 'test1.m' 81 | % 'test2.m' 82 | % 'test10.m' 83 | % 'test10-old.m' 84 | % 85 | %%% Directory Names: 86 | % D = {'A2-old\test.m';'A10\test.m';'A2\test.m';'A1archive.zip';'A1\test.m'}; 87 | % sort(D) % Wrong numeric order, and '-' sorts before '\': 88 | % ans = 89 | % 'A10\test.m' 90 | % 'A1\test.m' 91 | % 'A1archive.zip' 92 | % 'A2-old\test.m' 93 | % 'A2\test.m' 94 | % natsortfiles(D) % Shorter names before longer (dictionary sort): 95 | % ans = 96 | % 'A1archive.zip' 97 | % 'A1\test.m' 98 | % 'A2\test.m' 99 | % 'A2-old\test.m' 100 | % 'A10\test.m' 101 | % 102 | %% Input and Output Arguments %% 103 | % 104 | % Please see NATSORT for a full description of and the . 105 | % 106 | %%% Inputs (*=default): 107 | % X = Cell of Strings, with filenames or filepaths to be sorted. 108 | % xpr = String Token, regular expression to detect numeric substrings, '\d+'*. 109 | % can be supplied in any order and are passed directly to NATSORT. 110 | % 111 | %%% Outputs: 112 | % Y = Cell of Strings, with the filenames sorted according to . 113 | % ndx = Numeric Matrix, same size as . Indices such that Y = X(ndx). 114 | % 115 | % [Y,ndx] = natsortrows(X,*xpr,) 116 | 117 | %% Input Wrangling %% 118 | % 119 | assert(iscell(X),'First input must be a cell array.') 120 | tmp = cellfun('isclass',X,'char') & cellfun('size',X,1)<2 & cellfun('ndims',X)<3; 121 | assert(all(tmp(:)),'First input must be a cell array of strings (1xN character).') 122 | % 123 | %% Split and Sort File Names/Paths %% 124 | % 125 | % Split full filepaths into file [path,name,extension]: 126 | [pth,nam,ext] = cellfun(@fileparts,X(:),'UniformOutput',false); 127 | % Split path into {dir,subdir,subsubdir,...}: 128 | %pth = regexp(pth,filesep,'split'); % OS dependent 129 | pth = regexp(pth,'[/\\]','split'); % either / or \ 130 | len = cellfun('length',pth); 131 | vec(1:numel(len)) = {''}; 132 | % 133 | % Natural-order sort of the file extension, file name, and directory names: 134 | [~,ndx] = natsort(ext,varargin{:}); 135 | [~,ind] = natsort(nam(ndx),varargin{:}); 136 | ndx = ndx(ind); 137 | for k = max(len):-1:1 138 | idx = len>=k; 139 | vec(~idx) = {''}; 140 | vec(idx) = cellfun(@(c)c(k),pth(idx)); 141 | [~,ind] = natsort(vec(ndx),varargin{:}); 142 | ndx = ndx(ind); 143 | end 144 | % 145 | % Return the sorted array and indices: 146 | ndx = reshape(ndx,size(X)); 147 | X = X(ndx); 148 | % 149 | end 150 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%natsortfiles -------------------------------------------------------------------------------- /recognition/matrix2latex/matrix2latex.m: -------------------------------------------------------------------------------- 1 | function matrix2latex(matrix, filename, varargin) 2 | 3 | % function: matrix2latex(...) 4 | % Author: M. Koehler 5 | % Contact: koehler@in.tum.de 6 | % Version: 1.1 7 | % Date: May 09, 2004 8 | 9 | % This software is published under the GNU GPL, by the free software 10 | % foundation. For further reading see: http://www.gnu.org/licenses/licenses.html#GPL 11 | 12 | % Usage: 13 | % matrix2late(matrix, filename, varargs) 14 | % where 15 | % - matrix is a 2 dimensional numerical or cell array 16 | % - filename is a valid filename, in which the resulting latex code will 17 | % be stored 18 | % - varargs is one ore more of the following (denominator, value) combinations 19 | % + 'rowLabels', array -> Can be used to label the rows of the 20 | % resulting latex table 21 | % + 'columnLabels', array -> Can be used to label the columns of the 22 | % resulting latex table 23 | % + 'alignment', 'value' -> Can be used to specify the alginment of 24 | % the table within the latex document. Valid arguments are: 'l', 'c', 25 | % and 'r' for left, center, and right, respectively 26 | % + 'format', 'value' -> Can be used to format the input data. 'value' 27 | % has to be a valid format string, similar to the ones used in 28 | % fprintf('format', value); 29 | % + 'size', 'value' -> One of latex' recognized font-sizes, e.g. tiny, 30 | % HUGE, Large, large, LARGE, etc. 31 | % 32 | % Example input: 33 | % matrix = [1.5 1.764; 3.523 0.2]; 34 | % rowLabels = {'row 1', 'row 2'}; 35 | % columnLabels = {'col 1', 'col 2'}; 36 | % matrix2latex(matrix, 'out.tex', 'rowLabels', rowLabels, 'columnLabels', columnLabels, 'alignment', 'c', 'format', '%-6.2f', 'size', 'tiny'); 37 | % 38 | % The resulting latex file can be included into any latex document by: 39 | % /input{out.tex} 40 | % 41 | % Enjoy life!!! 42 | 43 | rowLabels = []; 44 | colLabels = []; 45 | alignment = 'l'; 46 | format = []; 47 | textsize = []; 48 | if (rem(nargin,2) == 1 || nargin < 2) 49 | error('matrix2latex: ', 'Incorrect number of arguments to %s.', mfilename); 50 | end 51 | 52 | okargs = {'rowlabels','columnlabels', 'alignment', 'format', 'size'}; 53 | for j=1:2:(nargin-2) 54 | pname = varargin{j}; 55 | pval = varargin{j+1}; 56 | k = strmatch(lower(pname), okargs); 57 | if isempty(k) 58 | error('matrix2latex: ', 'Unknown parameter name: %s.', pname); 59 | elseif length(k)>1 60 | error('matrix2latex: ', 'Ambiguous parameter name: %s.', pname); 61 | else 62 | switch(k) 63 | case 1 % rowlabels 64 | rowLabels = pval; 65 | if isnumeric(rowLabels) 66 | rowLabels = cellstr(num2str(rowLabels(:))); 67 | end 68 | case 2 % column labels 69 | colLabels = pval; 70 | if isnumeric(colLabels) 71 | colLabels = cellstr(num2str(colLabels(:))); 72 | end 73 | case 3 % alignment 74 | alignment = lower(pval); 75 | if alignment == 'right' 76 | alignment = 'r'; 77 | end 78 | if alignment == 'left' 79 | alignment = 'l'; 80 | end 81 | if alignment == 'center' 82 | alignment = 'c'; 83 | end 84 | if alignment ~= 'l' && alignment ~= 'c' && alignment ~= 'r' 85 | alignment = 'l'; 86 | warning('matrix2latex: ', 'Unkown alignment. (Set it to \''left\''.)'); 87 | end 88 | case 4 % format 89 | format = lower(pval); 90 | case 5 % format 91 | textsize = pval; 92 | end 93 | end 94 | end 95 | 96 | fid = fopen(filename, 'w'); 97 | 98 | width = size(matrix, 2); 99 | height = size(matrix, 1); 100 | 101 | if isnumeric(matrix) 102 | matrix = num2cell(matrix); 103 | for h=1:height 104 | for w=1:width 105 | if(~isempty(format)) 106 | matrix{h, w} = num2str(matrix{h, w}, format); 107 | else 108 | matrix{h, w} = num2str(matrix{h, w}); 109 | end 110 | end 111 | end 112 | end 113 | 114 | if(~isempty(textsize)) 115 | fprintf(fid, '\\begin{%s}', textsize); 116 | end 117 | 118 | fprintf(fid, '\\begin{tabular}{|'); 119 | 120 | if(~isempty(rowLabels)) 121 | fprintf(fid, 'l|'); 122 | end 123 | for i=1:width 124 | fprintf(fid, '%c|', alignment); 125 | end 126 | fprintf(fid, '}\r\n'); 127 | 128 | fprintf(fid, '\\hline\r\n'); 129 | 130 | if(~isempty(colLabels)) 131 | if(~isempty(rowLabels)) 132 | fprintf(fid, '&'); 133 | end 134 | for w=1:width-1 135 | fprintf(fid, '\\textbf{%s}&', colLabels{w}); 136 | end 137 | fprintf(fid, '\\textbf{%s}\\\\\\hline\r\n', colLabels{width}); 138 | end 139 | 140 | for h=1:height 141 | if(~isempty(rowLabels)) 142 | fprintf(fid, '\\textbf{%s}&', rowLabels{h}); 143 | end 144 | for w=1:width-1 145 | fprintf(fid, '%s&', matrix{h, w}); 146 | end 147 | fprintf(fid, '%s\\\\\\hline\r\n', matrix{h, width}); 148 | end 149 | 150 | fprintf(fid, '\\end{tabular}\r\n'); 151 | 152 | if(~isempty(textsize)) 153 | fprintf(fid, '\\end{%s}', textsize); 154 | end 155 | 156 | fclose(fid); -------------------------------------------------------------------------------- /tracking/freezeColors.m: -------------------------------------------------------------------------------- 1 | function freezeColors(varargin) 2 | % freezeColors Lock colors of plot, enabling multiple colormaps per figure. (v2.3) 3 | % 4 | % Problem: There is only one colormap per figure. This function provides 5 | % an easy solution when plots using different colomaps are desired 6 | % in the same figure. 7 | % 8 | % freezeColors freezes the colors of graphics objects in the current axis so 9 | % that subsequent changes to the colormap (or caxis) will not change the 10 | % colors of these objects. freezeColors works on any graphics object 11 | % with CData in indexed-color mode: surfaces, images, scattergroups, 12 | % bargroups, patches, etc. It works by converting CData to true-color rgb 13 | % based on the colormap active at the time freezeColors is called. 14 | % 15 | % The original indexed color data is saved, and can be restored using 16 | % unfreezeColors, making the plot once again subject to the colormap and 17 | % caxis. 18 | % 19 | % 20 | % Usage: 21 | % freezeColors applies to all objects in current axis (gca), 22 | % freezeColors(axh) same, but works on axis axh. 23 | % 24 | % Example: 25 | % subplot(2,1,1); imagesc(X); colormap hot; freezeColors 26 | % subplot(2,1,2); imagesc(Y); colormap hsv; freezeColors etc... 27 | % 28 | % Note: colorbars must also be frozen. Due to Matlab 'improvements' this can 29 | % no longer be done with freezeColors. Instead, please 30 | % use the function CBFREEZE by Carlos Adrian Vargas Aguilera 31 | % that can be downloaded from the MATLAB File Exchange 32 | % (http://www.mathworks.com/matlabcentral/fileexchange/24371) 33 | % 34 | % h=colorbar; cbfreeze(h), or simply cbfreeze(colorbar) 35 | % 36 | % For additional examples, see test/test_main.m 37 | % 38 | % Side effect on render mode: freezeColors does not work with the painters 39 | % renderer, because Matlab doesn't support rgb color data in 40 | % painters mode. If the current renderer is painters, freezeColors 41 | % changes it to zbuffer. This may have unexpected effects on other aspects 42 | % of your plots. 43 | % 44 | % See also unfreezeColors, freezeColors_pub.html, cbfreeze. 45 | % 46 | % 47 | % John Iversen (iversen@nsi.edu) 3/23/05 48 | % 49 | 50 | % Changes: 51 | % JRI (iversen@nsi.edu) 4/19/06 Correctly handles scaled integer cdata 52 | % JRI 9/1/06 should now handle all objects with cdata: images, surfaces, 53 | % scatterplots. (v 2.1) 54 | % JRI 11/11/06 Preserves NaN colors. Hidden option (v 2.2, not uploaded) 55 | % JRI 3/17/07 Preserve caxis after freezing--maintains colorbar scale (v 2.3) 56 | % JRI 4/12/07 Check for painters mode as Matlab doesn't support rgb in it. 57 | % JRI 4/9/08 Fix preserving caxis for objects within hggroups (e.g. contourf) 58 | % JRI 4/7/10 Change documentation for colorbars 59 | 60 | % Hidden option for NaN colors: 61 | % Missing data are often represented by NaN in the indexed color 62 | % data, which renders transparently. This transparency will be preserved 63 | % when freezing colors. If instead you wish such gaps to be filled with 64 | % a real color, add 'nancolor',[r g b] to the end of the arguments. E.g. 65 | % freezeColors('nancolor',[r g b]) or freezeColors(axh,'nancolor',[r g b]), 66 | % where [r g b] is a color vector. This works on images & pcolor, but not on 67 | % surfaces. 68 | % Thanks to Fabiano Busdraghi and Jody Klymak for the suggestions. Bugfixes 69 | % attributed in the code. 70 | 71 | % Free for all uses, but please retain the following: 72 | % Original Author: 73 | % John Iversen, 2005-10 74 | % john_iversen@post.harvard.edu 75 | 76 | appdatacode = 'JRI__freezeColorsData'; 77 | 78 | [h, nancolor] = checkArgs(varargin); 79 | 80 | %gather all children with scaled or indexed CData 81 | cdatah = getCDataHandles(h); 82 | 83 | %current colormap 84 | cmap = colormap; 85 | nColors = size(cmap,1); 86 | cax = caxis; 87 | 88 | % convert object color indexes into colormap to true-color data using 89 | % current colormap 90 | for hh = cdatah', 91 | g = get(hh); 92 | 93 | %preserve parent axis clim 94 | parentAx = getParentAxes(hh); 95 | originalClim = get(parentAx, 'clim'); 96 | 97 | % Note: Special handling of patches: For some reason, setting 98 | % cdata on patches created by bar() yields an error, 99 | % so instead we'll set facevertexcdata instead for patches. 100 | if ~strcmp(g.Type,'patch'), 101 | cdata = g.CData; 102 | else 103 | cdata = g.FaceVertexCData; 104 | end 105 | 106 | %get cdata mapping (most objects (except scattergroup) have it) 107 | if isfield(g,'CDataMapping'), 108 | scalemode = g.CDataMapping; 109 | else 110 | scalemode = 'scaled'; 111 | end 112 | 113 | %save original indexed data for use with unfreezeColors 114 | siz = size(cdata); 115 | setappdata(hh, appdatacode, {cdata scalemode}); 116 | 117 | %convert cdata to indexes into colormap 118 | if strcmp(scalemode,'scaled'), 119 | %4/19/06 JRI, Accommodate scaled display of integer cdata: 120 | % in MATLAB, uint * double = uint, so must coerce cdata to double 121 | % Thanks to O Yamashita for pointing this need out 122 | idx = ceil( (double(cdata) - cax(1)) / (cax(2)-cax(1)) * nColors); 123 | else %direct mapping 124 | idx = cdata; 125 | %10/8/09 in case direct data is non-int (e.g. image;freezeColors) 126 | % (Floor mimics how matlab converts data into colormap index.) 127 | % Thanks to D Armyr for the catch 128 | idx = floor(idx); 129 | end 130 | 131 | %clamp to [1, nColors] 132 | idx(idx<1) = 1; 133 | idx(idx>nColors) = nColors; 134 | 135 | %handle nans in idx 136 | nanmask = isnan(idx); 137 | idx(nanmask)=1; %temporarily replace w/ a valid colormap index 138 | 139 | %make true-color data--using current colormap 140 | realcolor = zeros(siz); 141 | for i = 1:3, 142 | c = cmap(idx,i); 143 | c = reshape(c,siz); 144 | c(nanmask) = nancolor(i); %restore Nan (or nancolor if specified) 145 | realcolor(:,:,i) = c; 146 | end 147 | 148 | %apply new true-color color data 149 | 150 | %true-color is not supported in painters renderer, so switch out of that 151 | if strcmp(get(gcf,'renderer'), 'painters'), 152 | set(gcf,'renderer','zbuffer'); 153 | end 154 | 155 | %replace original CData with true-color data 156 | if ~strcmp(g.Type,'patch'), 157 | set(hh,'CData',realcolor); 158 | else 159 | set(hh,'faceVertexCData',permute(realcolor,[1 3 2])) 160 | end 161 | 162 | %restore clim (so colorbar will show correct limits) 163 | if ~isempty(parentAx), 164 | set(parentAx,'clim',originalClim) 165 | end 166 | 167 | end %loop on indexed-color objects 168 | 169 | 170 | % ============================================================================ % 171 | % Local functions 172 | 173 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 174 | %% getCDataHandles -- get handles of all descendents with indexed CData 175 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 176 | 177 | function hout = getCDataHandles(h) 178 | % getCDataHandles Find all objects with indexed CData 179 | 180 | %recursively descend object tree, finding objects with indexed CData 181 | % An exception: don't include children of objects that themselves have CData: 182 | % for example, scattergroups are non-standard hggroups, with CData. Changing 183 | % such a group's CData automatically changes the CData of its children, 184 | % (as well as the children's handles), so there's no need to act on them. 185 | 186 | error(nargchk(1,1,nargin,'struct')) 187 | 188 | hout = []; 189 | if isempty(h),return;end 190 | 191 | ch = get(h,'children'); 192 | for hh = ch' 193 | g = get(hh); 194 | if isfield(g,'CData'), %does object have CData? 195 | %is it indexed/scaled? 196 | if ~isempty(g.CData) && isnumeric(g.CData) && size(g.CData,3)==1, 197 | hout = [hout; hh]; %#ok %yes, add to list 198 | end 199 | else %no CData, see if object has any interesting children 200 | hout = [hout; getCDataHandles(hh)]; %#ok 201 | end 202 | end 203 | 204 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 205 | %% getParentAxes -- return handle of axes object to which a given object belongs 206 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 207 | function hAx = getParentAxes(h) 208 | % getParentAxes Return enclosing axes of a given object (could be self) 209 | 210 | error(nargchk(1,1,nargin,'struct')) 211 | %object itself may be an axis 212 | if strcmp(get(h,'type'),'axes'), 213 | hAx = h; 214 | return 215 | end 216 | 217 | parent = get(h,'parent'); 218 | if (strcmp(get(parent,'type'), 'axes')), 219 | hAx = parent; 220 | else 221 | hAx = getParentAxes(parent); 222 | end 223 | 224 | 225 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 226 | %% checkArgs -- Validate input arguments 227 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 228 | 229 | function [h, nancolor] = checkArgs(args) 230 | % checkArgs Validate input arguments to freezeColors 231 | 232 | nargs = length(args); 233 | error(nargchk(0,3,nargs,'struct')) 234 | 235 | %grab handle from first argument if we have an odd number of arguments 236 | if mod(nargs,2), 237 | h = args{1}; 238 | if ~ishandle(h), 239 | error('JRI:freezeColors:checkArgs:invalidHandle',... 240 | 'The first argument must be a valid graphics handle (to an axis)') 241 | end 242 | % 4/2010 check if object to be frozen is a colorbar 243 | if strcmp(get(h,'Tag'),'Colorbar'), 244 | if ~exist('cbfreeze.m'), 245 | warning('JRI:freezeColors:checkArgs:cannotFreezeColorbar',... 246 | ['You seem to be attempting to freeze a colorbar. This no longer'... 247 | 'works. Please read the help for freezeColors for the solution.']) 248 | else 249 | cbfreeze(h); 250 | return 251 | end 252 | end 253 | args{1} = []; 254 | nargs = nargs-1; 255 | else 256 | h = gca; 257 | end 258 | 259 | %set nancolor if that option was specified 260 | nancolor = [nan nan nan]; 261 | if nargs == 2, 262 | if strcmpi(args{end-1},'nancolor'), 263 | nancolor = args{end}; 264 | if ~all(size(nancolor)==[1 3]), 265 | error('JRI:freezeColors:checkArgs:badColorArgument',... 266 | 'nancolor must be [r g b] vector'); 267 | end 268 | nancolor(nancolor>1) = 1; nancolor(nancolor<0) = 0; 269 | else 270 | error('JRI:freezeColors:checkArgs:unrecognizedOption',... 271 | 'Unrecognized option (%s). Only ''nancolor'' is valid.',args{end-1}) 272 | end 273 | end 274 | 275 | 276 | -------------------------------------------------------------------------------- /tracking/trackerMain_otb_wangchen.m: -------------------------------------------------------------------------------- 1 | function [results] = trackerMain_otb_wangchen(p, im, bg_area, fg_area, area_resize_factor) 2 | % KCC: Kernel Cross-Correlator 3 | % Visual Tracking Using KCC 4 | % 5 | % Copyright (C) 2017 6 | % Author: Wang Chen wang.chen@zoho.com Nanyang Technological University 7 | % Zhang Le zhang.le@adsc.com Advanced Digital Sciences Center 8 | % 9 | % This file is part of KCC. 10 | % 11 | % KCC is free software: you can redistribute it and/or modify 12 | % it under the terms of the GNU General Public License as published by 13 | % the Free Software Foundation, either version 3 of the License, or 14 | % (at your option) any later version. 15 | % 16 | % KCC is distributed in the hope that it will be useful, 17 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | % GNU General Public License for more details. 20 | % 21 | % You should have received a copy of the GNU General Public License 22 | % along with KCC. If not, see . 23 | 24 | %% INITIALIZATION 25 | num_frames = numel(p.img_files); 26 | % used for OTB-13 benchmark 27 | OTB_rect_positions = zeros(num_frames, 4); 28 | pos = p.init_pos; 29 | target_sz = p.target_sz; 30 | num_frames = numel(p.img_files); 31 | % patch of the target + padding 32 | patch_padded = getSubwindow(im, pos, p.norm_bg_area, bg_area); 33 | % initialize hist model 34 | new_pwp_model = true; 35 | [bg_hist, fg_hist] = updateHistModel(new_pwp_model, patch_padded, bg_area, fg_area, target_sz, p.norm_bg_area, p.n_bins, p.grayscale_sequence); 36 | new_pwp_model = false; 37 | % Hann (cosine) window 38 | if isToolboxAvailable('Signal Processing Toolbox') 39 | hann_window = single(hann(p.cf_response_size(1)) * hann(p.cf_response_size(2))'); 40 | else 41 | hann_window = single(myHann(p.cf_response_size(1)) * myHann(p.cf_response_size(2))'); 42 | end 43 | % gaussian-shaped desired response, centred in (1,1) 44 | % bandwidth proportional to target size 45 | output_sigma = sqrt(prod(p.norm_target_sz)) * p.output_sigma_factor / p.hog_cell_size; 46 | y = gaussianResponse(p.cf_response_size, output_sigma); 47 | yf = fft2(y); 48 | %% SCALE ADAPTATION INITIALIZATION 49 | if p.scale_adaptation 50 | % Code from DSST 51 | scale_factor = 1; 52 | base_target_sz = target_sz; 53 | scale_sigma = sqrt(p.num_scales) * p.scale_sigma_factor; 54 | ss = (1:p.num_scales) - ceil(p.num_scales/2); 55 | ys = exp(-0.5 * (ss.^2) / scale_sigma^2); 56 | 57 | ys=zeros(size(ys)); 58 | ys(1)=1; 59 | ysf = ((fft(ys))); 60 | if mod(p.num_scales,2) == 0 61 | scale_window = single(hann(p.num_scales+1)); 62 | scale_window = scale_window(2:end); 63 | else 64 | scale_window = single(hann(p.num_scales)); 65 | end; 66 | 67 | ss = 1:p.num_scales; 68 | scale_factors = p.scale_step.^(ceil(p.num_scales/2) - ss); 69 | 70 | if p.scale_model_factor^2 * prod(p.norm_target_sz) > p.scale_model_max_area 71 | p.scale_model_factor = sqrt(p.scale_model_max_area/prod(p.norm_target_sz)); 72 | end 73 | 74 | scale_model_sz = floor(p.norm_target_sz * p.scale_model_factor); 75 | % find maximum and minimum scales 76 | min_scale_factor = p.scale_step ^ ceil(log(max(5 ./ bg_area)) / log(p.scale_step)); 77 | max_scale_factor = p.scale_step ^ floor(log(min([size(im,1) size(im,2)] ./ target_sz)) / log(p.scale_step)); 78 | end 79 | 80 | %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 81 | t_imread = 0; 82 | %% MAIN LOOP 83 | tic; 84 | for frame = 1:num_frames 85 | 86 | if frame>1 87 | tic_imread = tic; 88 | im = imread([p.img_path p.img_files{frame}]); 89 | t_imread = t_imread + toc(tic_imread); 90 | %% TESTING step 91 | % extract patch of size bg_area and resize to norm_bg_area 92 | im_patch_cf = getSubwindow(im, pos, p.norm_bg_area, bg_area); 93 | pwp_search_area = round(p.norm_pwp_search_area / area_resize_factor); 94 | % extract patch of size pwp_search_area and resize to norm_pwp_search_area 95 | im_patch_pwp = getSubwindow(im, pos, p.norm_pwp_search_area, pwp_search_area); 96 | % compute feature map 97 | xt = getFeatureMap(im_patch_cf, p.feature_type, p.cf_response_size, p.hog_cell_size); 98 | % apply Hann window 99 | xt_windowed = bsxfun(@times, hann_window, xt); 100 | % compute FFT 101 | xtf = fft2(xt_windowed); 102 | % Correlation between filter and test patch gives the response 103 | % Solve diagonal system per pixel. 104 | if p.den_per_channel 105 | hf = hf_num ./ (hf_den + p.lambda); 106 | else 107 | hf = bsxfun(@rdivide, hf_num, sum(hf_den, 3)+p.lambda); 108 | end 109 | response_cf = ensure_real(ifft2(sum(conj(hf) .* xtf, 3))); 110 | 111 | % Crop square search region (in feature pixels). 112 | response_cf = cropFilterResponse(response_cf, ... 113 | floor_odd(p.norm_delta_area / p.hog_cell_size)); 114 | if p.hog_cell_size > 1 115 | % Scale up to match center likelihood resolution. 116 | response_cf = mexResize(response_cf, p.norm_delta_area,'auto'); 117 | end 118 | 119 | [likelihood_map] = getColourMap(im_patch_pwp, bg_hist, fg_hist, p.n_bins, p.grayscale_sequence); 120 | % (TODO) in theory it should be at 0.5 (unseen colors shoud have max entropy) 121 | likelihood_map(isnan(likelihood_map)) = 0; 122 | 123 | % each pixel of response_pwp loosely represents the likelihood that 124 | % the target (of size norm_target_sz) is centred on it 125 | response_pwp = getCenterLikelihood(likelihood_map, p.norm_target_sz); 126 | 127 | %% ESTIMATION 128 | response = mergeResponses(response_cf, response_pwp, p.merge_factor, p.merge_method); 129 | [row, col] = find(response == max(response(:)), 1); 130 | center = (1+p.norm_delta_area) / 2; 131 | pos = pos + ([row, col] - center) / area_resize_factor; 132 | rect_position = [pos([2,1]) - target_sz([2,1])/2, target_sz([2,1])]; 133 | 134 | %% SCALE SPACE SEARCH 135 | if p.scale_adaptation 136 | current_patch = getScalePatch(im, pos, base_target_sz, scale_factor, scale_window, scale_model_sz, p.hog_scale_cell_size); 137 | ksf = gaussian_correlation_scale_single(im_patch_scale, current_patch, p.scale_sigma); 138 | scale_response = abs(ifft((model_hf.*ksf))); 139 | [max_value, recovered_scale] = max(scale_response(:)); 140 | 141 | %set the scale 142 | scale_factor = scale_factor / scale_factors(recovered_scale); 143 | % fprintf('frame %d: recovered scale is %.2f:, current sclae factor is %.2f:\n', frame,recovered_scale,scale_factor) 144 | 145 | if scale_factor < min_scale_factor 146 | scale_factor = min_scale_factor; 147 | elseif scale_factor > max_scale_factor 148 | scale_factor = max_scale_factor; 149 | end 150 | % use new scale to update bboxes for target, filter, bg and fg models 151 | target_sz = round(base_target_sz * scale_factor); 152 | avg_dim = sum(target_sz)/2; 153 | bg_area = round(target_sz + avg_dim); 154 | if(bg_area(2)>size(im,2)), bg_area(2)=size(im,2)-1; end 155 | if(bg_area(1)>size(im,1)), bg_area(1)=size(im,1)-1; end 156 | 157 | bg_area = bg_area - mod(bg_area - target_sz, 2); 158 | fg_area = round(target_sz - avg_dim * p.inner_padding); 159 | fg_area = fg_area + mod(bg_area - fg_area, 2); 160 | % Compute the rectangle with (or close to) params.fixed_area and 161 | % same aspect ratio as the target bboxgetScaleSubwindow_v1 162 | area_resize_factor = sqrt(p.fixed_area/prod(bg_area)); 163 | end 164 | 165 | if p.visualization_dbg==1 166 | mySubplot(2,1,5,1,im_patch_cf,'FG+BG','gray'); 167 | mySubplot(2,1,5,2,likelihood_map,'obj.likelihood','parula'); 168 | mySubplot(2,1,5,3,response_cf,'CF response','parula'); 169 | mySubplot(2,1,5,4,response_pwp,'center likelihood','parula'); 170 | mySubplot(2,1,5,5,response,'merged response','parula'); 171 | drawnow 172 | end 173 | end 174 | 175 | %% TRAINING 176 | % extract patch of size bg_area and resize to norm_bg_area 177 | im_patch_bg = getSubwindow(im, pos, p.norm_bg_area, bg_area); 178 | % compute feature map, of cf_response_size 179 | xt = getFeatureMap(im_patch_bg, p.feature_type, p.cf_response_size, p.hog_cell_size); 180 | % apply Hann window 181 | xt = bsxfun(@times, hann_window, xt); 182 | % compute FFT 183 | xtf = fft2(xt); 184 | %% FILTER UPDATE 185 | % Compute expectations over circular shifts, 186 | % therefore divide by number of pixels. 187 | new_hf_num = bsxfun(@times, conj(yf), xtf) / prod(p.cf_response_size); 188 | new_hf_den = (conj(xtf) .* xtf) / prod(p.cf_response_size); 189 | 190 | if frame == 1 191 | % first frame, train with a single image 192 | hf_den = new_hf_den; 193 | hf_num = new_hf_num; 194 | else 195 | % subsequent frames, update the model by linear interpolation 196 | hf_den = (1 - p.learning_rate_cf) * hf_den + p.learning_rate_cf * new_hf_den; 197 | hf_num = (1 - p.learning_rate_cf) * hf_num + p.learning_rate_cf * new_hf_num; 198 | 199 | %% BG/FG MODEL UPDATE 200 | % patch of the target + padding 201 | [bg_hist, fg_hist] = updateHistModel(new_pwp_model, im_patch_bg, bg_area, fg_area, target_sz, p.norm_bg_area, p.n_bins, p.grayscale_sequence, bg_hist, fg_hist, p.learning_rate_pwp); 202 | end 203 | 204 | %% SCALE UPDATE 205 | if p.scale_adaptation 206 | im_patch_scale_frame = getScaleSubwindow_v1(im, pos, base_target_sz, scale_factors*scale_factor, scale_window, scale_model_sz, p.hog_scale_cell_size); 207 | 208 | if frame == 1 209 | im_patch_scale=im_patch_scale_frame; 210 | else 211 | im_patch_scale=(1 - p.learning_rate_scale)*im_patch_scale + p.learning_rate_scale*im_patch_scale_frame; 212 | end 213 | 214 | ksf = gaussian_correlation_scale_single(im_patch_scale, im_patch_scale(:,uint8(size(im_patch_scale,2)/2)), p.scale_sigma); 215 | model_hf = ysf'./(ksf+0.1); 216 | end 217 | 218 | % update bbox position 219 | if frame==1, rect_position = [pos([2,1]) - target_sz([2,1])/2, target_sz([2,1])]; end 220 | 221 | rect_position_padded = [pos([2,1]) - bg_area([2,1])/2, bg_area([2,1])]; 222 | 223 | OTB_rect_positions(frame,:) = rect_position; 224 | 225 | if p.fout > 0, fprintf(p.fout,'%.2f,%.2f,%.2f,%.2f\n', rect_position(1),rect_position(2),rect_position(3),rect_position(4)); end 226 | 227 | %% VISUALIZATION 228 | if p.visualization == 1 229 | 230 | figure(1) 231 | imshow(im) 232 | rectangle('Position',rect_position, 'LineWidth',2, 'EdgeColor','g'); 233 | rectangle('Position',rect_position_padded, 'LineWidth',2, 'LineStyle','--', 'EdgeColor','b'); 234 | drawnow 235 | 236 | end 237 | end 238 | elapsed_time = toc; 239 | % save data for OTB-13 benchmark 240 | results.type = 'rect'; 241 | results.res = OTB_rect_positions; 242 | results.fps = num_frames/(elapsed_time - t_imread); 243 | end 244 | 245 | % Reimplementation of Hann window (in case signal processing toolbox is missing) 246 | function H = myHann(X) 247 | H = .5*(1 - cos(2*pi*(0:X-1)'/(X-1))); 248 | end 249 | 250 | % We want odd regions so that the central pixel can be exact 251 | function y = floor_odd(x) 252 | y = 2*floor((x-1) / 2) + 1; 253 | end 254 | 255 | function y = ensure_real(x) 256 | assert(norm(imag(x(:))) <= 1e-5 * norm(real(x(:)))); 257 | y = real(x); 258 | end -------------------------------------------------------------------------------- /recognition/natsortfiles/natsort.m: -------------------------------------------------------------------------------- 1 | function [X,ndx,dbg] = natsort(X,xpr,varargin) %#ok<*SPERR> 2 | % Alphanumeric / Natural-Order sort the strings in a cell array of strings. 3 | % 4 | % (c) 2017 Stephen Cobeldick 5 | % 6 | % Alphanumeric sort of a cell array of strings: sorts by character order 7 | % and also by the values of any numbers that are within the strings. The 8 | % default is case-insensitive ascending with integer number substrings: 9 | % optional inputs control the sort direction, case sensitivity, and the 10 | % number substring matching (see the section "Number Substrings" below). 11 | % 12 | %%% Syntax: 13 | % Y = natsort(X) 14 | % Y = natsort(X,xpr) 15 | % Y = natsort(X,xpr,) 16 | % [Y,ndx] = natsort(X,...); 17 | % 18 | % To sort filenames or filepaths use NATSORTFILES (File Exchange 47434). 19 | % To sort the rows of a cell array of strings use NATSORTROWS (File Exchange 47433). 20 | % 21 | % See also NATSORTFILES NATSORTROWS SORTROWS SORT CELLSTR REGEXP SSCANF NUM2ORDINAL NUM2WORDS NUM2BIP NUM2SIP INTMAX 22 | % 23 | %% Number Substrings %% 24 | % 25 | % By default consecutive digit characters are interpreted as an integer. 26 | % The optional regular expression pattern permits the numbers to also 27 | % include a +/- sign, a decimal point, exponent E-notation or any literal 28 | % characters, quantifiers or look-around requirements. For more information: 29 | % http://www.mathworks.com/help/matlab/matlab_prog/regular-expressions.html 30 | % 31 | % The substrings are then parsed by SSCANF into numeric variables, using 32 | % either the *default format '%f', or the user-supplied format specifier. 33 | % 34 | % This table shows some example regular expression patterns for some common 35 | % notations and ways of writing numbers (see section "Examples" for more): 36 | % 37 | % Regular | Number Substring | Number Substring | SSCANF 38 | % Expression: | Match Examples: | Match Description: | Format Specifier: 39 | % ==============|==================|===============================|================== 40 | % * \d+ | 0, 1, 234, 56789 | unsigned integer | %f %u %lu %i 41 | % --------------|------------------|-------------------------------|------------------ 42 | % (-|+)?\d+ | -1, 23, +45, 678 | integer with optional +/- sign| %f %d %ld %i 43 | % --------------|------------------|-------------------------------|------------------ 44 | % \d+(\.\d+)? | 012, 3.45, 678.9 | integer or decimal | %f 45 | % --------------|------------------|-------------------------------|------------------ 46 | % \d+|Inf|NaN | 123, 4, Inf, NaN | integer, infinite or NaN value| %f 47 | % --------------|------------------|-------------------------------|------------------ 48 | % \d+\.\d+e\d+ | 0.123e4, 5.67e08 | exponential notation | %f 49 | % --------------|------------------|-------------------------------|------------------ 50 | % 0[0-7]+ | 012, 03456, 0700 | octal prefix & notation | %o %i 51 | % --------------|------------------|-------------------------------|------------------ 52 | % 0X[0-9A-F]+ | 0X0, 0XFF, 0X7C4 | hexadecimal prefix & notation | %x %i 53 | % --------------|------------------|-------------------------------|------------------ 54 | % 0B[01]+ | 0B101, 0B0010111 | binary prefix & notation | %b 55 | % --------------|------------------|-------------------------------|------------------ 56 | % 57 | % The SSCANF format specifier (including %b) can include literal characters 58 | % and skipped fields. The octal, hexadecimal and binary prefixes are optional. 59 | % For more information: http://www.mathworks.com/help/matlab/ref/sscanf.html 60 | % 61 | %% Relative Sort Order %% 62 | % 63 | % The sort order of the number substrings relative to the characters 64 | % can be controlled by providing one of the following string options: 65 | % 66 | % Option Token:| Relative Sort Order: | Example: 67 | % =============|======================================|==================== 68 | % 'beforechar' | numbers < char(0:end) | '1' < '.' < 'A' 69 | % -------------|--------------------------------------|-------------------- 70 | % 'afterchar' | char(0:end) < numbers | '.' < 'A' < '1' 71 | % -------------|--------------------------------------|-------------------- 72 | % 'asdigit' *| char(0:47) < numbers < char(48:end) | '.' < '1' < 'A' 73 | % -------------|--------------------------------------|-------------------- 74 | % 75 | % Note that the digit characters have character values 48 to 57, inclusive. 76 | % 77 | %% Examples %% 78 | % 79 | %%% Integer number substrings: 80 | % A = {'a2', 'a10', 'a1'}; 81 | % sort(A) 82 | % ans = 'a1' 'a10' 'a2' 83 | % natsort(A) 84 | % ans = 'a1' 'a2' 'a10' 85 | % 86 | %%% Multiple number substrings (e.g. release version numbers): 87 | % B = {'v10.6', 'v9.10', 'v9.5', 'v10.10', 'v9.10.20', 'v9.10.8'}; 88 | % sort(B) 89 | % ans = 'v10.10' 'v10.6' 'v9.10' 'v9.10.20' 'v9.10.8' 'v9.5' 90 | % natsort(B) 91 | % ans = 'v9.5' 'v9.10' 'v9.10.8' 'v9.10.20' 'v10.6' 'v10.10' 92 | % 93 | %%% Integer, decimal or Inf number substrings, possibly with +/- signs: 94 | % C = {'test+Inf', 'test11.5', 'test-1.4', 'test', 'test-Inf', 'test+0.3'}; 95 | % sort(C) 96 | % ans = 'test' 'test+0.3' 'test+Inf' 'test-1.4' 'test-Inf' 'test11.5' 97 | % natsort(C, '(-|+)?(Inf|\d+(\.\d+)?)') 98 | % ans = 'test' 'test-Inf' 'test-1.4' 'test+0.3' 'test11.5' 'test+Inf' 99 | % 100 | %%% Integer or decimal number substrings, possibly with an exponent: 101 | % D = {'0.56e007', '', '4.3E-2', '10000', '9.8'}; 102 | % sort(D) 103 | % ans = '' '0.56e007' '10000' '4.3E-2' '9.8' 104 | % natsort(D, '\d+(\.\d+)?(E(+|-)?\d+)?') 105 | % ans = '' '4.3E-2' '9.8' '10000' '0.56e007' 106 | % 107 | %%% Hexadecimal number substrings (possibly with '0X' prefix): 108 | % E = {'a0X7C4z', 'a0X5z', 'a0X18z', 'aFz'}; 109 | % sort(E) 110 | % ans = 'a0X18z' 'a0X5z' 'a0X7C4z' 'aFz' 111 | % natsort(E, '(?<=a)(0X)?[0-9A-F]+', '%x') 112 | % ans = 'a0X5z' 'aFz' 'a0X18z' 'a0X7C4z' 113 | % 114 | %%% Binary number substrings (possibly with '0B' prefix): 115 | % F = {'a11111000100z', 'a0B101z', 'a0B000000000011000z', 'a1111z'}; 116 | % sort(F) 117 | % ans = 'a0B000000000011000z' 'a0B101z' 'a11111000100z' 'a1111z' 118 | % natsort(F, '(0B)?[01]+', '%b') 119 | % ans = 'a0B101z' 'a1111z' 'a0B000000000011000z' 'a11111000100z' 120 | % 121 | %%% uint64 number substrings (with full precision!): 122 | % natsort({'a18446744073709551615z', 'a18446744073709551614z'}, [], '%lu') 123 | % ans = 'a18446744073709551614z' 'a18446744073709551615z' 124 | % 125 | %%% Case sensitivity: 126 | % G = {'a2', 'A20', 'A1', 'a10', 'A2', 'a1'}; 127 | % natsort(G, [], 'ignorecase') % default 128 | % ans = 'A1' 'a1' 'a2' 'A2' 'a10' 'A20' 129 | % natsort(G, [], 'matchcase') 130 | % ans = 'A1' 'A2' 'A20' 'a1' 'a2' 'a10' 131 | % 132 | %%% Sort direction: 133 | % H = {'2', 'a', '3', 'B', '1'}; 134 | % natsort(H, [], 'ascend') % default 135 | % ans = '1' '2' '3' 'a' 'B' 136 | % natsort(H, [], 'descend') 137 | % ans = 'B' 'a' '3' '2' '1' 138 | % 139 | %%% Relative sort-order of number substrings compared to characters: 140 | % X = num2cell(char(32+randperm(63))); 141 | % cell2mat(natsort(X, [], 'asdigit')) % default 142 | % ans = '!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' 143 | % cell2mat(natsort(X, [], 'beforechar')) 144 | % ans = '0123456789!"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' 145 | % cell2mat(natsort(X, [], 'afterchar')) 146 | % ans = '!"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_0123456789' 147 | % 148 | %% Input and Output Arguments %% 149 | % 150 | %%% Inputs (*=default): 151 | % X = Cell of Strings, with strings to be sorted into natural-order. 152 | % xpr = String Token, regular expression to detect number substrings, *'\d+'. 153 | % string tokens can be entered in any order, as many as required: 154 | % - Case sensitive/insensitive matching: 'matchcase'/'ignorecase'*. 155 | % - Sort direction: 'descend'/'ascend'*. 156 | % - Relative sort of numbers: 'beforechar'/'afterchar'/'asdigit'*. 157 | % - The SSCANF number conversion format, e.g.: *'%f', '%x', '%i', etc. 158 | % 159 | %%% Outputs: 160 | % Y = Cell of Strings, with all strings sorted into natural-order. 161 | % ndx = Numeric Array, such that Y = X(ndx). The same size as . 162 | % dbg = Cell Array of all parsed characters and number values. Each row is 163 | % one string, linear-indexed from . Helps to debug string parsing. 164 | % 165 | % [X,ndx,dbg] = natsort(X,*xpr,) 166 | 167 | %% Input Wrangling %% 168 | % 169 | assert(iscell(X),'First input must be a cell array.') 170 | tmp = cellfun('isclass',X,'char') & 2>cellfun('size',X,1) & 3>cellfun('ndims',X); 171 | assert(all(tmp(:)),'First input must be a cell array of strings (1xN character).') 172 | % 173 | % Regular expression: 174 | if nargin<2 || isnumeric(xpr)&&isempty(xpr) 175 | xpr = '\d+'; 176 | else 177 | assert(ischar(xpr)&&isrow(xpr),'Second input must be a regular expression.') 178 | end 179 | % 180 | % Optional arguments: 181 | tmp = cellfun('isclass',varargin,'char') & 1==cellfun('size',varargin,1) & 2==cellfun('ndims',varargin); 182 | assert(all(tmp(:)),'All optional arguments must be strings (1xN character).') 183 | % Character case matching: 184 | MatL = strcmpi(varargin,'matchcase'); 185 | CasL = strcmpi(varargin,'ignorecase')|MatL; 186 | % Sort direction: 187 | DesL = strcmpi(varargin,'descend'); 188 | DirL = strcmpi(varargin,'ascend')|DesL; 189 | % Relative sort-order of numbers compared to characters: 190 | BefL = strcmpi(varargin,'beforechar'); 191 | AftL = strcmpi(varargin,'afterchar'); 192 | RsoL = strcmpi(varargin,'asdigit')|BefL|AftL; 193 | % SSCANF conversion format: 194 | FmtL = ~(CasL|DirL|RsoL); 195 | % 196 | if nnz(DirL)>1 197 | error('Sort direction is overspecified:%s\b.',sprintf(' ''%s'',',varargin{DirL})) 198 | end 199 | % 200 | if nnz(RsoL)>1 201 | error('Relative sort-order is overspecified:%s\b.',sprintf(' ''%s'',',varargin{RsoL})) 202 | end 203 | % 204 | FmtN = nnz(FmtL); 205 | if FmtN>1 206 | error('Overspecified optional arguments:%s\b.',sprintf(' ''%s'',',varargin{FmtL})) 207 | end 208 | % 209 | %% Split Strings %% 210 | % 211 | % Split strings into number and remaining substrings: 212 | [MtS,MtE,MtC,SpC] = regexpi(X(:),xpr,'start','end','match','split',varargin{CasL}); 213 | % 214 | % Determine lengths: 215 | MtcD = cellfun(@minus,MtE,MtS,'UniformOutput',false); 216 | LenZ = cellfun('length',X(:))-cellfun(@sum,MtcD); 217 | LenY = max(LenZ); 218 | LenX = numel(MtC); 219 | % 220 | dbg = cell(LenX,LenY); 221 | NuI = false(LenX,LenY); 222 | ChI = false(LenX,LenY); 223 | ChA = char(double(ChI)); 224 | % 225 | ndx = 1:LenX; 226 | for k = ndx(LenZ>0) 227 | % Determine indices of numbers and characters: 228 | ChI(k,1:LenZ(k)) = true; 229 | if ~isempty(MtS{k}) 230 | tmp = MtE{k} - cumsum(MtcD{k}); 231 | dbg(k,tmp) = MtC{k}; 232 | NuI(k,tmp) = true; 233 | ChI(k,tmp) = false; 234 | end 235 | % Transfer characters into char array: 236 | if any(ChI(k,:)) 237 | tmp = SpC{k}; 238 | ChA(k,ChI(k,:)) = [tmp{:}]; 239 | end 240 | end 241 | % 242 | %% Convert Number Substrings %% 243 | % 244 | if FmtN % One format specifier 245 | fmt = varargin{FmtL}; 246 | err = ['Format specifier results in an empty output from sscanf: ''',fmt,'''']; 247 | P = '(? double 268 | NuA(NuI) = sscanf(sprintf('%s\v',dbg{NuI}),'%f\v'); 269 | end 270 | % Note: NuA's class is determined by SSCANF. 271 | NuA(~NuI) = 0; 272 | NuA = reshape(NuA,LenX,LenY); 273 | % 274 | %% Debugging Array %% 275 | % 276 | if nargout>2 277 | for k = reshape(find(NuI),1,[]) 278 | dbg{k} = NuA(k); 279 | end 280 | for k = reshape(find(ChI),1,[]) 281 | dbg{k} = ChA(k); 282 | end 283 | end 284 | % 285 | %% Sort %% 286 | % 287 | if ~any(MatL) % ignorecase 288 | ChA = upper(ChA); 289 | end 290 | % 291 | ide = ndx.'; 292 | % From the last column to the first... 293 | for n = LenY:-1:1 294 | % ...sort the characters and number values: 295 | [C,idc] = sort(ChA(ndx,n),1,varargin{DirL}); 296 | [~,idn] = sort(NuA(ndx,n),1,varargin{DirL}); 297 | % ...keep only relevant indices: 298 | jdc = ChI(ndx(idc),n); % character 299 | jdn = NuI(ndx(idn),n); % number 300 | jde = ~ChI(ndx,n)&~NuI(ndx,n); % empty 301 | % ...define the sort-order of numbers and characters: 302 | jdo = any(AftL)|(~any(BefL)&C<48); 303 | % ...then combine these indices in the requested direction: 304 | if any(DesL) % descending 305 | idx = [idc(jdc&~jdo);idn(jdn);idc(jdc&jdo);ide(jde)]; 306 | else % ascending 307 | idx = [ide(jde);idc(jdc&jdo);idn(jdn);idc(jdc&~jdo)]; 308 | end 309 | ndx = ndx(idx); 310 | end 311 | % 312 | ndx = reshape(ndx,size(X)); 313 | X = X(ndx); 314 | % 315 | end 316 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%natsort -------------------------------------------------------------------------------- /recognition/natsortfiles/html/natsortfiles_doc.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | NATSORTFILES Examples

NATSORTFILES Examples

The function NATSORTFILES sorts a cell array of filenames or filepaths, taking into account any number values within the strings. This is known as a "natural order sort" or an "alphanumeric sort". Note that MATLAB's inbuilt SORT function sorts the character codes only (as does sort in most programming languages).

NATSORTFILES is not a naive natural-order sort, but sorts the filenames and file extensions separately: this prevents the file extension separator character . and file extension itself from influencing the sort order of the complete filename+extension. Thus NATSORTFILES sorts shorter filenames before longer ones, which is known as a "dictionary sort". For the same reason filepaths are split at each path-separator character, and each directory level is sorted separately. See the "Explanation" sections below for more details.

For sorting the rows of a cell array of strings use NATSORTROWS.

For sorting a cell array of strings use NATSORT.

Contents

Basic Usage:

By default NATSORTFILES interprets consecutive digits as being part of a single integer, each number is considered to be as wide as one letter:

A = {'a2.txt', 'a10.txt', 'a1.txt'};
 66 | sort(A)
 67 | natsortfiles(A)
 68 | 
ans = 
 69 |     'a1.txt'    'a10.txt'    'a2.txt'
 70 | ans = 
 71 |     'a1.txt'    'a2.txt'    'a10.txt'
 72 | 

Output 2: Sort Index

The second output argument is a numeric array of the sort indices ndx, such that Y = X(ndx) where Y = natsortfiles(X):

[~,ndx] = natsortfiles(A)
 73 | 
ndx =
 74 |      3     1     2
 75 | 

Example with DIR and a Cell Array

One common situation is using DIR to identify files in a folder, sort them into the correct order, and then loop over them: below is an example of how to do this. Remember to preallocate all output arrays before the loop!

D = 'natsortfiles_test'; % directory path
 76 | S = dir(fullfile(D,'*.txt')); % get list of files in directory
 77 | N = natsortfiles({S.name}); % sort file names into order
 78 | for k = 1:numel(N)
 79 | 	fullfile(D,N{k})
 80 | end
 81 | 
ans =
 82 | natsortfiles_test\A_1.txt
 83 | ans =
 84 | natsortfiles_test\A_1-new.txt
 85 | ans =
 86 | natsortfiles_test\A_1_new.txt
 87 | ans =
 88 | natsortfiles_test\A_2.txt
 89 | ans =
 90 | natsortfiles_test\A_3.txt
 91 | ans =
 92 | natsortfiles_test\A_10.txt
 93 | ans =
 94 | natsortfiles_test\A_100.txt
 95 | ans =
 96 | natsortfiles_test\A_200.txt
 97 | 

Example with DIR and a Structure

Users who need to access the DIR structure fields can use NATSORTFILE's second output to sort DIR's output structure into the correct order:

D = 'natsortfiles_test'; % directory path
 98 | S = dir(fullfile(D,'*.txt')); % get list of files in directory
 99 | [~,ndx] = natsortfiles({S.name}); % indices of correct order
100 | S = S(ndx); % sort structure using indices
101 | for k = 1:numel(N)
102 | 	S(k).name;
103 | 	S(k).date;
104 | end
105 | 

Explanation: Dictionary Sort

Filenames and file extensions are separated by the extension separator, the period character ., which gets sorted after all of the characters from 0 to 45, including !"#$%&'()*+,-, the space character, and all of the control characters (newlines, tabs, etc). This means that a naive sort or natural-order sort will sort some short filenames after longer filenames. In order to provide the correct dictionary sort, with shorter filenames first, NATSORTFILES sorts the filenames and file extensions separately:

B = {'test_ccc.m'; 'test-aaa.m'; 'test.m'; 'test.bbb.m'};
106 | sort(B) % '-' sorts before '.'
107 | natsort(B) % '-' sorts before '.'
108 | natsortfiles(B) % correct dictionary sort
109 | 
ans = 
110 |     'test-aaa.m'
111 |     'test.bbb.m'
112 |     'test.m'
113 |     'test_ccc.m'
114 | ans = 
115 |     'test-aaa.m'
116 |     'test.bbb.m'
117 |     'test.m'
118 |     'test_ccc.m'
119 | ans = 
120 |     'test.m'
121 |     'test-aaa.m'
122 |     'test.bbb.m'
123 |     'test_ccc.m'
124 | 

Explanation: Filenames

NATSORTFILES combines a dictionary sort with a natural-order sort, so that the number values within the filenames are taken into consideration:

C = {'test2.m'; 'test10-old.m'; 'test.m'; 'test10.m'; 'test1.m'};
125 | sort(C) % Wrong numeric order.
126 | natsort(C) % Correct numeric order, but longer before shorter.
127 | natsortfiles(C) % Correct numeric order and dictionary sort.
128 | 
ans = 
129 |     'test.m'
130 |     'test1.m'
131 |     'test10-old.m'
132 |     'test10.m'
133 |     'test2.m'
134 | ans = 
135 |     'test.m'
136 |     'test1.m'
137 |     'test2.m'
138 |     'test10-old.m'
139 |     'test10.m'
140 | ans = 
141 |     'test.m'
142 |     'test1.m'
143 |     'test2.m'
144 |     'test10.m'
145 |     'test10-old.m'
146 | 

Explanation: Filepaths

For the same reason, filepaths are split at each file path separator character (both / and \ are considered to be file path separators) and every level of directory names are sorted separately. This ensures that the directory names are sorted with a dictionary sort and that any numbers are taken into consideration:

D = {'A2-old\test.m';'A10\test.m';'A2\test.m';'AXarchive.zip';'A1\test.m'};
147 | sort(D) % Wrong numeric order, and '-' sorts before '\':
148 | natsort(D) % correct numeric order, but longer before shorter.
149 | natsortfiles(D) % correct numeric order and dictionary sort.
150 | 
ans = 
151 |     'A10\test.m'
152 |     'A1\test.m'
153 |     'A2-old\test.m'
154 |     'A2\test.m'
155 |     'AXarchive.zip'
156 | ans = 
157 |     'A1\test.m'
158 |     'A2-old\test.m'
159 |     'A2\test.m'
160 |     'A10\test.m'
161 |     'AXarchive.zip'
162 | ans = 
163 |     'AXarchive.zip'
164 |     'A1\test.m'
165 |     'A2\test.m'
166 |     'A2-old\test.m'
167 |     'A10\test.m'
168 | 

Regular Expression: Decimal Numbers, E-notation, +/- Sign.

NATSORTFILES is a wrapper for NATSORT, which means all of NATSORT's options are also supported. In particular the number recognition can be customized to detect numbers with decimal digits, E-notation, a +/- sign, or other specific features. This detection is defined by providing an appropriate regular expression: see NATSORT for details and examples.

E = {'test24.csv','test1.8.csv','test5.csv','test3.3.csv','test12.csv'};
169 | natsortfiles(E,'\d+(\.\d+)?')
170 | 
ans = 
171 |     'test1.8.csv'    'test3.3.csv'    'test5.csv'    'test12.csv'    'test24.csv'
172 | 
-------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------