From 1141737439126c2fee84495360aab9279e34a83a Mon Sep 17 00:00:00 2001 From: JeffsanC Date: Thu, 23 Nov 2017 10:37:50 +0800 Subject: [PATCH] add recognition --- recognition/.gitignore | 107 ++++++ recognition/activity_recognition.m | 57 ++++ recognition/analyse_parameters.m | 6 + recognition/comparison_results.txt | 17 + recognition/data_conversion.m | 41 +++ recognition/find_parameter.m | 12 + recognition/gaussian_kernel.m | 11 + recognition/kcc.m | 9 + recognition/kcc_train.m | 17 + recognition/matrix2latex/license.txt | 24 ++ recognition/matrix2latex/matrix2latex.m | 156 +++++++++ .../natsortfiles/html/natsortfiles_doc.html | 270 +++++++++++++++ recognition/natsortfiles/license.txt | 25 ++ recognition/natsortfiles/natsort.m | 316 ++++++++++++++++++ recognition/natsortfiles/natsortfiles.m | 150 +++++++++ recognition/natsortfiles/natsortfiles_doc.m | 94 ++++++ recognition/show_example.m | 59 ++++ recognition/show_results.m | 90 +++++ 18 files changed, 1461 insertions(+) create mode 100644 recognition/.gitignore create mode 100644 recognition/activity_recognition.m create mode 100644 recognition/analyse_parameters.m create mode 100644 recognition/comparison_results.txt create mode 100644 recognition/data_conversion.m create mode 100644 recognition/find_parameter.m create mode 100644 recognition/gaussian_kernel.m create mode 100644 recognition/kcc.m create mode 100644 recognition/kcc_train.m create mode 100644 recognition/matrix2latex/license.txt create mode 100644 recognition/matrix2latex/matrix2latex.m create mode 100644 recognition/natsortfiles/html/natsortfiles_doc.html create mode 100644 recognition/natsortfiles/license.txt create mode 100644 recognition/natsortfiles/natsort.m create mode 100644 recognition/natsortfiles/natsortfiles.m create mode 100644 recognition/natsortfiles/natsortfiles_doc.m create mode 100644 recognition/show_example.m create mode 100644 recognition/show_results.m diff --git a/recognition/.gitignore b/recognition/.gitignore new file mode 100644 index 0000000..115843a --- /dev/null +++ b/recognition/.gitignore @@ -0,0 +1,107 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +WARD1.0 +*.asv +data.mat +results.mat +performances.mat +*.mat \ No newline at end of file diff --git a/recognition/activity_recognition.m b/recognition/activity_recognition.m new file mode 100644 index 0000000..aade204 --- /dev/null +++ b/recognition/activity_recognition.m @@ -0,0 +1,57 @@ +function results = activity_recognition(lambda, sigma) + close all + load('data.mat'); + + if nargin < 2 + lambda = 0.0015; + sigma = 1; + end + + sequence = 76:125; + time_kcc = zeros(13,1); + time_dtw = zeros(13,1); + + %% examples + for subject = 1:size(data,1) + for activity = 1:size(data, 2) + for samples = 1:5%size(data, 3) %only one subject has the 6th sample in only one activity + if isempty(data{subject, activity, samples}) + continue; + end + + train = data{subject, activity, samples}(sequence, :); + tic + correlator = kcc_train(train, lambda, sigma); + time_kcc(activity) = time_kcc(activity) + toc; + + for activity_test = 1:size(data, 2) + for samples_test = 1:5%size(data, 3) %only one subject has the 6th sample in only one activity + if isempty(data{subject, activity_test, samples_test}) + continue; + end + + test = data{subject, activity_test, samples_test}(sequence, :); + + tic + response(subject, 5*(activity-1)+ samples, 5*(activity_test-1)+ samples_test) = kcc(test, correlator); + time_kcc(activity_test) = time_kcc(activity_test) + toc; + + tic +% distance(subject, 5*(activity-1)+ samples, 5*(activity_test-1)+ samples_test) = 0; + distance(subject, 5*(activity-1)+ samples, 5*(activity_test-1)+ samples_test) = dtw(train', test'); + time_dtw(activity_test) = time_dtw(activity_test) + toc; + end + end + end + end + end + + time_use = [time_kcc, time_dtw]; + filename = 'results.mat'; + save(filename, 'response', 'distance', 'time_use'); + [accuracy_kcc, accuracy_dtw] = show_results(filename); + results = [accuracy_dtw, accuracy_kcc, time_dtw, time_kcc, sigma, lambda]; + fprintf('accuracy_dtw: %f; accuracy_kcc: %f; time_dtw: %f, time_kcc: %f; sigma: %f lambda: %f\n', ... + results(1), results(2), results(3), results(4), results(5), results(6)); + +end diff --git a/recognition/analyse_parameters.m b/recognition/analyse_parameters.m new file mode 100644 index 0000000..a21858d --- /dev/null +++ b/recognition/analyse_parameters.m @@ -0,0 +1,6 @@ +% clc +% clear +load('performances_refine_refin.mat'); +plot3(performances(:,end-1), performances(:,end), performances(:,2),'.') +performances(:,[end-1,end,2]) +max(performances(:,2)) \ No newline at end of file diff --git a/recognition/comparison_results.txt b/recognition/comparison_results.txt new file mode 100644 index 0000000..74e55bf --- /dev/null +++ b/recognition/comparison_results.txt @@ -0,0 +1,17 @@ +\begin{tabular}{|l|l|l|l|} +\hline +74&63.5&119.0911&161.0318\\\hline +75.5&66&116.525&156.9842\\\hline +72&72.5&116.66&157.161\\\hline +96&87&116.6862&157.8734\\\hline +93&80&116.7369&157.3694\\\hline +94.5&84&113.9792&153.9453\\\hline +95.5&80&115.4979&155.2064\\\hline +95&83&116.6258&157.0647\\\hline +94.5&80&116.5067&157.0048\\\hline +99.5&79&116.4776&157.2347\\\hline +100&95&116.5865&157.0245\\\hline +97&86&116.4139&157.0018\\\hline +92.5&69&115.3224&155.4016\\\hline +90.6923&78.8462&116.393&156.9464\\\hline +\end{tabular} diff --git a/recognition/data_conversion.m b/recognition/data_conversion.m new file mode 100644 index 0000000..5925a48 --- /dev/null +++ b/recognition/data_conversion.m @@ -0,0 +1,41 @@ +clear; clc +% You need to download the WARD dataset to current folder. +% +folder = './WARD1.0/'; +addpath('./natsortfiles/') +files = dir(folder); +fileIndex = find([files.isdir]); +fileIndex = fileIndex(3:end); +files = files(fileIndex); +data={}; + +files = natsortfiles({files(:).name}); + +for i = 1:length(files) + subfolder = files(i); + matfolders = dir(strcat(folder,subfolder{1})); + matIndex = find(~[matfolders.isdir]); + matfolders = matfolders(matIndex); + matfolder_files = natsortfiles({matfolders(:).name}); + + for j = 1:length(matfolder_files) + matfiles = matfolder_files(j); + filename = strcat(folder, subfolder,'/',matfiles{1}); + wd = load(filename{1}); + reading=[]; + for k=1:5 + col = wd.WearableData.Reading{k}; + col(isinf (col))=0; + col(isnan (col))=0; + tran = col-mean(col); + reading = [reading, tran./2./max(abs(tran))+0.5]; + reading(isnan(reading))=0; + end + number = sscanf(filename{1},'./WARD1.0/Subject%d/a%dt%d.mat'); + data{number(1),number(2), number(3)} = reading; +% data{i,j}.name = filename; + end +end + +save('data.mat', 'data'); +clear diff --git a/recognition/find_parameter.m b/recognition/find_parameter.m new file mode 100644 index 0000000..f1f04a5 --- /dev/null +++ b/recognition/find_parameter.m @@ -0,0 +1,12 @@ +clc +clear +lambda = 0.0014:0.0001:0.0020; +sigma = 0.5:0.1:1.1; + +performances=[]; +for i = 1:numel(lambda) + for j = 1:numel(sigma) + performance = activity_recognition(lambda(i), sigma(j)); + performances = [performance; performances]; + end +end diff --git a/recognition/gaussian_kernel.m b/recognition/gaussian_kernel.m new file mode 100644 index 0000000..9cb83ce --- /dev/null +++ b/recognition/gaussian_kernel.m @@ -0,0 +1,11 @@ +function kf = gaussian_kernel(xf, yf, sigma) + % Calculating the gaussian kernel vertor + % Copyright Wang Chen, Nanyang Technoglogical University + + N = numel(xf); + xx = xf(:)' * xf(:) / N; + yy = yf(:)' * yf(:) / N; + xy = mean((ifft(xf .* conj(yf))),2); + kf = exp(-1 / sigma^2 * (xx + yy - 2 * xy) / N); +end + diff --git a/recognition/kcc.m b/recognition/kcc.m new file mode 100644 index 0000000..8ebc579 --- /dev/null +++ b/recognition/kcc.m @@ -0,0 +1,9 @@ +function [response, output] = kcc(test, correlator) + % Calculating the response + % Copyright Wang Chen, Nanyang Technoglogical University + test_fft = fft(test); + kernel_fft = fft(gaussian_kernel(test_fft, correlator.sample_fft, correlator.sigma)); + output = abs(ifft(correlator.correlator_fft.*kernel_fft)); + response = max(output);%/sum(output); +end + diff --git a/recognition/kcc_train.m b/recognition/kcc_train.m new file mode 100644 index 0000000..9d98ff7 --- /dev/null +++ b/recognition/kcc_train.m @@ -0,0 +1,17 @@ +function correlator = kcc_train(sample, lambda, sigma) + % Training the correlator based on one sample + % Copyright Wang Chen, Nanyang Technoglogical University + if nargin < 3 + sigma = 0.3; + end + if nargin < 2 + lambda = 0.1; + end + + correlator.sigma = sigma; + target_fft = ones(size(sample,1),1); + correlator.sample_fft = fft(sample); + kernel_fft = fft(gaussian_kernel(correlator.sample_fft, correlator.sample_fft, correlator.sigma)); + correlator.correlator_fft = target_fft./(kernel_fft + lambda); +end + diff --git a/recognition/matrix2latex/license.txt b/recognition/matrix2latex/license.txt new file mode 100644 index 0000000..5871e1b --- /dev/null +++ b/recognition/matrix2latex/license.txt @@ -0,0 +1,24 @@ +Copyright (c) 2009, Moritz Koehler +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/recognition/matrix2latex/matrix2latex.m b/recognition/matrix2latex/matrix2latex.m new file mode 100644 index 0000000..ba736fb --- /dev/null +++ b/recognition/matrix2latex/matrix2latex.m @@ -0,0 +1,156 @@ +function matrix2latex(matrix, filename, varargin) + +% function: matrix2latex(...) +% Author: M. Koehler +% Contact: koehler@in.tum.de +% Version: 1.1 +% Date: May 09, 2004 + +% This software is published under the GNU GPL, by the free software +% foundation. For further reading see: http://www.gnu.org/licenses/licenses.html#GPL + +% Usage: +% matrix2late(matrix, filename, varargs) +% where +% - matrix is a 2 dimensional numerical or cell array +% - filename is a valid filename, in which the resulting latex code will +% be stored +% - varargs is one ore more of the following (denominator, value) combinations +% + 'rowLabels', array -> Can be used to label the rows of the +% resulting latex table +% + 'columnLabels', array -> Can be used to label the columns of the +% resulting latex table +% + 'alignment', 'value' -> Can be used to specify the alginment of +% the table within the latex document. Valid arguments are: 'l', 'c', +% and 'r' for left, center, and right, respectively +% + 'format', 'value' -> Can be used to format the input data. 'value' +% has to be a valid format string, similar to the ones used in +% fprintf('format', value); +% + 'size', 'value' -> One of latex' recognized font-sizes, e.g. tiny, +% HUGE, Large, large, LARGE, etc. +% +% Example input: +% matrix = [1.5 1.764; 3.523 0.2]; +% rowLabels = {'row 1', 'row 2'}; +% columnLabels = {'col 1', 'col 2'}; +% matrix2latex(matrix, 'out.tex', 'rowLabels', rowLabels, 'columnLabels', columnLabels, 'alignment', 'c', 'format', '%-6.2f', 'size', 'tiny'); +% +% The resulting latex file can be included into any latex document by: +% /input{out.tex} +% +% Enjoy life!!! + + rowLabels = []; + colLabels = []; + alignment = 'l'; + format = []; + textsize = []; + if (rem(nargin,2) == 1 || nargin < 2) + error('matrix2latex: ', 'Incorrect number of arguments to %s.', mfilename); + end + + okargs = {'rowlabels','columnlabels', 'alignment', 'format', 'size'}; + for j=1:2:(nargin-2) + pname = varargin{j}; + pval = varargin{j+1}; + k = strmatch(lower(pname), okargs); + if isempty(k) + error('matrix2latex: ', 'Unknown parameter name: %s.', pname); + elseif length(k)>1 + error('matrix2latex: ', 'Ambiguous parameter name: %s.', pname); + else + switch(k) + case 1 % rowlabels + rowLabels = pval; + if isnumeric(rowLabels) + rowLabels = cellstr(num2str(rowLabels(:))); + end + case 2 % column labels + colLabels = pval; + if isnumeric(colLabels) + colLabels = cellstr(num2str(colLabels(:))); + end + case 3 % alignment + alignment = lower(pval); + if alignment == 'right' + alignment = 'r'; + end + if alignment == 'left' + alignment = 'l'; + end + if alignment == 'center' + alignment = 'c'; + end + if alignment ~= 'l' && alignment ~= 'c' && alignment ~= 'r' + alignment = 'l'; + warning('matrix2latex: ', 'Unkown alignment. (Set it to \''left\''.)'); + end + case 4 % format + format = lower(pval); + case 5 % format + textsize = pval; + end + end + end + + fid = fopen(filename, 'w'); + + width = size(matrix, 2); + height = size(matrix, 1); + + if isnumeric(matrix) + matrix = num2cell(matrix); + for h=1:height + for w=1:width + if(~isempty(format)) + matrix{h, w} = num2str(matrix{h, w}, format); + else + matrix{h, w} = num2str(matrix{h, w}); + end + end + end + end + + if(~isempty(textsize)) + fprintf(fid, '\\begin{%s}', textsize); + end + + fprintf(fid, '\\begin{tabular}{|'); + + if(~isempty(rowLabels)) + fprintf(fid, 'l|'); + end + for i=1:width + fprintf(fid, '%c|', alignment); + end + fprintf(fid, '}\r\n'); + + fprintf(fid, '\\hline\r\n'); + + if(~isempty(colLabels)) + if(~isempty(rowLabels)) + fprintf(fid, '&'); + end + for w=1:width-1 + fprintf(fid, '\\textbf{%s}&', colLabels{w}); + end + fprintf(fid, '\\textbf{%s}\\\\\\hline\r\n', colLabels{width}); + end + + for h=1:height + if(~isempty(rowLabels)) + fprintf(fid, '\\textbf{%s}&', rowLabels{h}); + end + for w=1:width-1 + fprintf(fid, '%s&', matrix{h, w}); + end + fprintf(fid, '%s\\\\\\hline\r\n', matrix{h, width}); + end + + fprintf(fid, '\\end{tabular}\r\n'); + + if(~isempty(textsize)) + fprintf(fid, '\\end{%s}', textsize); + end + + fclose(fid); \ No newline at end of file diff --git a/recognition/natsortfiles/html/natsortfiles_doc.html b/recognition/natsortfiles/html/natsortfiles_doc.html new file mode 100644 index 0000000..c827e03 --- /dev/null +++ b/recognition/natsortfiles/html/natsortfiles_doc.html @@ -0,0 +1,270 @@ + + + + + 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'};
+sort(A)
+natsortfiles(A)
+
ans = 
+    'a1.txt'    'a10.txt'    'a2.txt'
+ans = 
+    'a1.txt'    'a2.txt'    'a10.txt'
+

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)
+
ndx =
+     3     1     2
+

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
+S = dir(fullfile(D,'*.txt')); % get list of files in directory
+N = natsortfiles({S.name}); % sort file names into order
+for k = 1:numel(N)
+	fullfile(D,N{k})
+end
+
ans =
+natsortfiles_test\A_1.txt
+ans =
+natsortfiles_test\A_1-new.txt
+ans =
+natsortfiles_test\A_1_new.txt
+ans =
+natsortfiles_test\A_2.txt
+ans =
+natsortfiles_test\A_3.txt
+ans =
+natsortfiles_test\A_10.txt
+ans =
+natsortfiles_test\A_100.txt
+ans =
+natsortfiles_test\A_200.txt
+

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
+S = dir(fullfile(D,'*.txt')); % get list of files in directory
+[~,ndx] = natsortfiles({S.name}); % indices of correct order
+S = S(ndx); % sort structure using indices
+for k = 1:numel(N)
+	S(k).name;
+	S(k).date;
+end
+

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'};
+sort(B) % '-' sorts before '.'
+natsort(B) % '-' sorts before '.'
+natsortfiles(B) % correct dictionary sort
+
ans = 
+    'test-aaa.m'
+    'test.bbb.m'
+    'test.m'
+    'test_ccc.m'
+ans = 
+    'test-aaa.m'
+    'test.bbb.m'
+    'test.m'
+    'test_ccc.m'
+ans = 
+    'test.m'
+    'test-aaa.m'
+    'test.bbb.m'
+    'test_ccc.m'
+

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'};
+sort(C) % Wrong numeric order.
+natsort(C) % Correct numeric order, but longer before shorter.
+natsortfiles(C) % Correct numeric order and dictionary sort.
+
ans = 
+    'test.m'
+    'test1.m'
+    'test10-old.m'
+    'test10.m'
+    'test2.m'
+ans = 
+    'test.m'
+    'test1.m'
+    'test2.m'
+    'test10-old.m'
+    'test10.m'
+ans = 
+    'test.m'
+    'test1.m'
+    'test2.m'
+    'test10.m'
+    'test10-old.m'
+

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'};
+sort(D) % Wrong numeric order, and '-' sorts before '\':
+natsort(D) % correct numeric order, but longer before shorter.
+natsortfiles(D) % correct numeric order and dictionary sort.
+
ans = 
+    'A10\test.m'
+    'A1\test.m'
+    'A2-old\test.m'
+    'A2\test.m'
+    'AXarchive.zip'
+ans = 
+    'A1\test.m'
+    'A2-old\test.m'
+    'A2\test.m'
+    'A10\test.m'
+    'AXarchive.zip'
+ans = 
+    'AXarchive.zip'
+    'A1\test.m'
+    'A2\test.m'
+    'A2-old\test.m'
+    'A10\test.m'
+

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'};
+natsortfiles(E,'\d+(\.\d+)?')
+
ans = 
+    'test1.8.csv'    'test3.3.csv'    'test5.csv'    'test12.csv'    'test24.csv'
+
\ No newline at end of file diff --git a/recognition/natsortfiles/license.txt b/recognition/natsortfiles/license.txt new file mode 100644 index 0000000..d4ceefb --- /dev/null +++ b/recognition/natsortfiles/license.txt @@ -0,0 +1,25 @@ +Copyright (c) 2017, Stephen Cobeldick +Copyright (c) 2016, Stephen Cobeldick +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/recognition/natsortfiles/natsort.m b/recognition/natsortfiles/natsort.m new file mode 100644 index 0000000..b67b69b --- /dev/null +++ b/recognition/natsortfiles/natsort.m @@ -0,0 +1,316 @@ +function [X,ndx,dbg] = natsort(X,xpr,varargin) %#ok<*SPERR> +% Alphanumeric / Natural-Order sort the strings in a cell array of strings. +% +% (c) 2017 Stephen Cobeldick +% +% Alphanumeric sort of a cell array of strings: sorts by character order +% and also by the values of any numbers that are within the strings. The +% default is case-insensitive ascending with integer number substrings: +% optional inputs control the sort direction, case sensitivity, and the +% number substring matching (see the section "Number Substrings" below). +% +%%% Syntax: +% Y = natsort(X) +% Y = natsort(X,xpr) +% Y = natsort(X,xpr,) +% [Y,ndx] = natsort(X,...); +% +% To sort filenames or filepaths use NATSORTFILES (File Exchange 47434). +% To sort the rows of a cell array of strings use NATSORTROWS (File Exchange 47433). +% +% See also NATSORTFILES NATSORTROWS SORTROWS SORT CELLSTR REGEXP SSCANF NUM2ORDINAL NUM2WORDS NUM2BIP NUM2SIP INTMAX +% +%% Number Substrings %% +% +% By default consecutive digit characters are interpreted as an integer. +% The optional regular expression pattern permits the numbers to also +% include a +/- sign, a decimal point, exponent E-notation or any literal +% characters, quantifiers or look-around requirements. For more information: +% http://www.mathworks.com/help/matlab/matlab_prog/regular-expressions.html +% +% The substrings are then parsed by SSCANF into numeric variables, using +% either the *default format '%f', or the user-supplied format specifier. +% +% This table shows some example regular expression patterns for some common +% notations and ways of writing numbers (see section "Examples" for more): +% +% Regular | Number Substring | Number Substring | SSCANF +% Expression: | Match Examples: | Match Description: | Format Specifier: +% ==============|==================|===============================|================== +% * \d+ | 0, 1, 234, 56789 | unsigned integer | %f %u %lu %i +% --------------|------------------|-------------------------------|------------------ +% (-|+)?\d+ | -1, 23, +45, 678 | integer with optional +/- sign| %f %d %ld %i +% --------------|------------------|-------------------------------|------------------ +% \d+(\.\d+)? | 012, 3.45, 678.9 | integer or decimal | %f +% --------------|------------------|-------------------------------|------------------ +% \d+|Inf|NaN | 123, 4, Inf, NaN | integer, infinite or NaN value| %f +% --------------|------------------|-------------------------------|------------------ +% \d+\.\d+e\d+ | 0.123e4, 5.67e08 | exponential notation | %f +% --------------|------------------|-------------------------------|------------------ +% 0[0-7]+ | 012, 03456, 0700 | octal prefix & notation | %o %i +% --------------|------------------|-------------------------------|------------------ +% 0X[0-9A-F]+ | 0X0, 0XFF, 0X7C4 | hexadecimal prefix & notation | %x %i +% --------------|------------------|-------------------------------|------------------ +% 0B[01]+ | 0B101, 0B0010111 | binary prefix & notation | %b +% --------------|------------------|-------------------------------|------------------ +% +% The SSCANF format specifier (including %b) can include literal characters +% and skipped fields. The octal, hexadecimal and binary prefixes are optional. +% For more information: http://www.mathworks.com/help/matlab/ref/sscanf.html +% +%% Relative Sort Order %% +% +% The sort order of the number substrings relative to the characters +% can be controlled by providing one of the following string options: +% +% Option Token:| Relative Sort Order: | Example: +% =============|======================================|==================== +% 'beforechar' | numbers < char(0:end) | '1' < '.' < 'A' +% -------------|--------------------------------------|-------------------- +% 'afterchar' | char(0:end) < numbers | '.' < 'A' < '1' +% -------------|--------------------------------------|-------------------- +% 'asdigit' *| char(0:47) < numbers < char(48:end) | '.' < '1' < 'A' +% -------------|--------------------------------------|-------------------- +% +% Note that the digit characters have character values 48 to 57, inclusive. +% +%% Examples %% +% +%%% Integer number substrings: +% A = {'a2', 'a10', 'a1'}; +% sort(A) +% ans = 'a1' 'a10' 'a2' +% natsort(A) +% ans = 'a1' 'a2' 'a10' +% +%%% Multiple number substrings (e.g. release version numbers): +% B = {'v10.6', 'v9.10', 'v9.5', 'v10.10', 'v9.10.20', 'v9.10.8'}; +% sort(B) +% ans = 'v10.10' 'v10.6' 'v9.10' 'v9.10.20' 'v9.10.8' 'v9.5' +% natsort(B) +% ans = 'v9.5' 'v9.10' 'v9.10.8' 'v9.10.20' 'v10.6' 'v10.10' +% +%%% Integer, decimal or Inf number substrings, possibly with +/- signs: +% C = {'test+Inf', 'test11.5', 'test-1.4', 'test', 'test-Inf', 'test+0.3'}; +% sort(C) +% ans = 'test' 'test+0.3' 'test+Inf' 'test-1.4' 'test-Inf' 'test11.5' +% natsort(C, '(-|+)?(Inf|\d+(\.\d+)?)') +% ans = 'test' 'test-Inf' 'test-1.4' 'test+0.3' 'test11.5' 'test+Inf' +% +%%% Integer or decimal number substrings, possibly with an exponent: +% D = {'0.56e007', '', '4.3E-2', '10000', '9.8'}; +% sort(D) +% ans = '' '0.56e007' '10000' '4.3E-2' '9.8' +% natsort(D, '\d+(\.\d+)?(E(+|-)?\d+)?') +% ans = '' '4.3E-2' '9.8' '10000' '0.56e007' +% +%%% Hexadecimal number substrings (possibly with '0X' prefix): +% E = {'a0X7C4z', 'a0X5z', 'a0X18z', 'aFz'}; +% sort(E) +% ans = 'a0X18z' 'a0X5z' 'a0X7C4z' 'aFz' +% natsort(E, '(?<=a)(0X)?[0-9A-F]+', '%x') +% ans = 'a0X5z' 'aFz' 'a0X18z' 'a0X7C4z' +% +%%% Binary number substrings (possibly with '0B' prefix): +% F = {'a11111000100z', 'a0B101z', 'a0B000000000011000z', 'a1111z'}; +% sort(F) +% ans = 'a0B000000000011000z' 'a0B101z' 'a11111000100z' 'a1111z' +% natsort(F, '(0B)?[01]+', '%b') +% ans = 'a0B101z' 'a1111z' 'a0B000000000011000z' 'a11111000100z' +% +%%% uint64 number substrings (with full precision!): +% natsort({'a18446744073709551615z', 'a18446744073709551614z'}, [], '%lu') +% ans = 'a18446744073709551614z' 'a18446744073709551615z' +% +%%% Case sensitivity: +% G = {'a2', 'A20', 'A1', 'a10', 'A2', 'a1'}; +% natsort(G, [], 'ignorecase') % default +% ans = 'A1' 'a1' 'a2' 'A2' 'a10' 'A20' +% natsort(G, [], 'matchcase') +% ans = 'A1' 'A2' 'A20' 'a1' 'a2' 'a10' +% +%%% Sort direction: +% H = {'2', 'a', '3', 'B', '1'}; +% natsort(H, [], 'ascend') % default +% ans = '1' '2' '3' 'a' 'B' +% natsort(H, [], 'descend') +% ans = 'B' 'a' '3' '2' '1' +% +%%% Relative sort-order of number substrings compared to characters: +% X = num2cell(char(32+randperm(63))); +% cell2mat(natsort(X, [], 'asdigit')) % default +% ans = '!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' +% cell2mat(natsort(X, [], 'beforechar')) +% ans = '0123456789!"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' +% cell2mat(natsort(X, [], 'afterchar')) +% ans = '!"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_0123456789' +% +%% Input and Output Arguments %% +% +%%% Inputs (*=default): +% X = Cell of Strings, with strings to be sorted into natural-order. +% xpr = String Token, regular expression to detect number substrings, *'\d+'. +% string tokens can be entered in any order, as many as required: +% - Case sensitive/insensitive matching: 'matchcase'/'ignorecase'*. +% - Sort direction: 'descend'/'ascend'*. +% - Relative sort of numbers: 'beforechar'/'afterchar'/'asdigit'*. +% - The SSCANF number conversion format, e.g.: *'%f', '%x', '%i', etc. +% +%%% Outputs: +% Y = Cell of Strings, with all strings sorted into natural-order. +% ndx = Numeric Array, such that Y = X(ndx). The same size as . +% dbg = Cell Array of all parsed characters and number values. Each row is +% one string, linear-indexed from . Helps to debug string parsing. +% +% [X,ndx,dbg] = natsort(X,*xpr,) + +%% Input Wrangling %% +% +assert(iscell(X),'First input must be a cell array.') +tmp = cellfun('isclass',X,'char') & 2>cellfun('size',X,1) & 3>cellfun('ndims',X); +assert(all(tmp(:)),'First input must be a cell array of strings (1xN character).') +% +% Regular expression: +if nargin<2 || isnumeric(xpr)&&isempty(xpr) + xpr = '\d+'; +else + assert(ischar(xpr)&&isrow(xpr),'Second input must be a regular expression.') +end +% +% Optional arguments: +tmp = cellfun('isclass',varargin,'char') & 1==cellfun('size',varargin,1) & 2==cellfun('ndims',varargin); +assert(all(tmp(:)),'All optional arguments must be strings (1xN character).') +% Character case matching: +MatL = strcmpi(varargin,'matchcase'); +CasL = strcmpi(varargin,'ignorecase')|MatL; +% Sort direction: +DesL = strcmpi(varargin,'descend'); +DirL = strcmpi(varargin,'ascend')|DesL; +% Relative sort-order of numbers compared to characters: +BefL = strcmpi(varargin,'beforechar'); +AftL = strcmpi(varargin,'afterchar'); +RsoL = strcmpi(varargin,'asdigit')|BefL|AftL; +% SSCANF conversion format: +FmtL = ~(CasL|DirL|RsoL); +% +if nnz(DirL)>1 + error('Sort direction is overspecified:%s\b.',sprintf(' ''%s'',',varargin{DirL})) +end +% +if nnz(RsoL)>1 + error('Relative sort-order is overspecified:%s\b.',sprintf(' ''%s'',',varargin{RsoL})) +end +% +FmtN = nnz(FmtL); +if FmtN>1 + error('Overspecified optional arguments:%s\b.',sprintf(' ''%s'',',varargin{FmtL})) +end +% +%% Split Strings %% +% +% Split strings into number and remaining substrings: +[MtS,MtE,MtC,SpC] = regexpi(X(:),xpr,'start','end','match','split',varargin{CasL}); +% +% Determine lengths: +MtcD = cellfun(@minus,MtE,MtS,'UniformOutput',false); +LenZ = cellfun('length',X(:))-cellfun(@sum,MtcD); +LenY = max(LenZ); +LenX = numel(MtC); +% +dbg = cell(LenX,LenY); +NuI = false(LenX,LenY); +ChI = false(LenX,LenY); +ChA = char(double(ChI)); +% +ndx = 1:LenX; +for k = ndx(LenZ>0) + % Determine indices of numbers and characters: + ChI(k,1:LenZ(k)) = true; + if ~isempty(MtS{k}) + tmp = MtE{k} - cumsum(MtcD{k}); + dbg(k,tmp) = MtC{k}; + NuI(k,tmp) = true; + ChI(k,tmp) = false; + end + % Transfer characters into char array: + if any(ChI(k,:)) + tmp = SpC{k}; + ChA(k,ChI(k,:)) = [tmp{:}]; + end +end +% +%% Convert Number Substrings %% +% +if FmtN % One format specifier + fmt = varargin{FmtL}; + err = ['Format specifier results in an empty output from sscanf: ''',fmt,'''']; + P = '(? double + NuA(NuI) = sscanf(sprintf('%s\v',dbg{NuI}),'%f\v'); +end +% Note: NuA's class is determined by SSCANF. +NuA(~NuI) = 0; +NuA = reshape(NuA,LenX,LenY); +% +%% Debugging Array %% +% +if nargout>2 + for k = reshape(find(NuI),1,[]) + dbg{k} = NuA(k); + end + for k = reshape(find(ChI),1,[]) + dbg{k} = ChA(k); + end +end +% +%% Sort %% +% +if ~any(MatL) % ignorecase + ChA = upper(ChA); +end +% +ide = ndx.'; +% From the last column to the first... +for n = LenY:-1:1 + % ...sort the characters and number values: + [C,idc] = sort(ChA(ndx,n),1,varargin{DirL}); + [~,idn] = sort(NuA(ndx,n),1,varargin{DirL}); + % ...keep only relevant indices: + jdc = ChI(ndx(idc),n); % character + jdn = NuI(ndx(idn),n); % number + jde = ~ChI(ndx,n)&~NuI(ndx,n); % empty + % ...define the sort-order of numbers and characters: + jdo = any(AftL)|(~any(BefL)&C<48); + % ...then combine these indices in the requested direction: + if any(DesL) % descending + idx = [idc(jdc&~jdo);idn(jdn);idc(jdc&jdo);ide(jde)]; + else % ascending + idx = [ide(jde);idc(jdc&jdo);idn(jdn);idc(jdc&~jdo)]; + end + ndx = ndx(idx); +end +% +ndx = reshape(ndx,size(X)); +X = X(ndx); +% +end +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%natsort \ No newline at end of file diff --git a/recognition/natsortfiles/natsortfiles.m b/recognition/natsortfiles/natsortfiles.m new file mode 100644 index 0000000..ea51ebe --- /dev/null +++ b/recognition/natsortfiles/natsortfiles.m @@ -0,0 +1,150 @@ +function [X,ndx] = natsortfiles(X,varargin) +% Alphanumeric / Natural-Order sort of a cell array of filenames/filepaths. +% +% (c) 2017 Stephen Cobeldick +% +% Alphanumeric sort of a cell array of filenames or filepaths: sorts by +% character order and also by the values of any numbers that are within +% the strings. Filenames, file-extensions, and directories (if supplied) +% are split apart and are sorted separately: this ensures that shorter +% filenames sort before longer ones (i.e. just like a dictionary sort). +% +%%% Syntax: +% Y = natsortfiles(X) +% Y = natsortfiles(X,xpr) +% Y = natsortfiles(X,xpr,) +% [Y,ndx] = natsortfiles(X,...) +% +% To sort all of the strings in a cell array use NATSORT (File Exchange 34464). +% To sort the rows of a cell array of strings use NATSORTROWS (File Exchange 47433). +% +% See also NATSORT NATSORTROWS SORT SORTROWS NUM2SIP NUM2BIP CELLSTR REGEXP DIR FILEPARTS FULLFILE FILESEP +% +%% File Dependency %% +% +% NATSORTFILES requires the function NATSORT (File Exchange 34464). The inputs +% and are passed directly to NATSORT: see NATSORT for case +% sensitivity, sort direction, numeric substring matching, and other options. +% +%% Explanation %% +% +% Using SORT on filenames will sort any of char(0:45), including the printing +% characters ' !"#$%&''()*+,-', before the file extension separator character '.'. +% Therefore this function splits the name and extension and sorts them separately. +% +% Similarly the file separator character within filepaths can cause longer +% directory names to sort before shorter ones, as char(0:46)<'/' and char(0:91)<'\'. +% NATSORTFILES splits filepaths at each file separator character and sorts +% every level of the directory hierarchy separately, ensuring that shorter +% directory names sort before longer, regardless of the characters in the names. +% +%% Examples %% +% +%%% DIR and Cell Array: +% D = 'C:\Test'; +% S = dir(fullfile(D,'*.txt')); +% N = natsortfiles({S.name}); +% for k = 1:numel(N) +% fullfile(D,N{k}) +% end +% +% A = {'a2.txt', 'a10.txt', 'a1.txt'}; +% sort(A) % Wrong numeric order: +% ans = 'a1.txt' 'a10.txt' 'a2.txt' +% natsortfiles(A) +% ans = 'a1.txt' 'a2.txt' 'a10.txt' +% +% B = {'test_new.m'; 'test-old.m'; 'test.m'}; +% sort(B) % Note '-' sorts before '.': +% ans = +% 'test-old.m' +% 'test.m' +% 'test_new.m' +% natsortfiles(B) % Shorter names before longer (dictionary sort): +% ans = +% 'test.m' +% 'test-old.m' +% 'test_new.m' +% +% C = {'test2.m'; 'test10-old.m'; 'test.m'; 'test10.m'; 'test1.m'}; +% sort(C) % Wrong numeric order: +% ans = +% 'test.m' +% 'test1.m' +% 'test10-old.m' +% 'test10.m' +% 'test2.m' +% natsortfiles(C) % Correct numeric order, shorter names before longer: +% ans = +% 'test.m' +% 'test1.m' +% 'test2.m' +% 'test10.m' +% 'test10-old.m' +% +%%% Directory Names: +% D = {'A2-old\test.m';'A10\test.m';'A2\test.m';'A1archive.zip';'A1\test.m'}; +% sort(D) % Wrong numeric order, and '-' sorts before '\': +% ans = +% 'A10\test.m' +% 'A1\test.m' +% 'A1archive.zip' +% 'A2-old\test.m' +% 'A2\test.m' +% natsortfiles(D) % Shorter names before longer (dictionary sort): +% ans = +% 'A1archive.zip' +% 'A1\test.m' +% 'A2\test.m' +% 'A2-old\test.m' +% 'A10\test.m' +% +%% Input and Output Arguments %% +% +% Please see NATSORT for a full description of and the . +% +%%% Inputs (*=default): +% X = Cell of Strings, with filenames or filepaths to be sorted. +% xpr = String Token, regular expression to detect numeric substrings, '\d+'*. +% can be supplied in any order and are passed directly to NATSORT. +% +%%% Outputs: +% Y = Cell of Strings, with the filenames sorted according to . +% ndx = Numeric Matrix, same size as . Indices such that Y = X(ndx). +% +% [Y,ndx] = natsortrows(X,*xpr,) + +%% Input Wrangling %% +% +assert(iscell(X),'First input must be a cell array.') +tmp = cellfun('isclass',X,'char') & cellfun('size',X,1)<2 & cellfun('ndims',X)<3; +assert(all(tmp(:)),'First input must be a cell array of strings (1xN character).') +% +%% Split and Sort File Names/Paths %% +% +% Split full filepaths into file [path,name,extension]: +[pth,nam,ext] = cellfun(@fileparts,X(:),'UniformOutput',false); +% Split path into {dir,subdir,subsubdir,...}: +%pth = regexp(pth,filesep,'split'); % OS dependent +pth = regexp(pth,'[/\\]','split'); % either / or \ +len = cellfun('length',pth); +vec(1:numel(len)) = {''}; +% +% Natural-order sort of the file extension, file name, and directory names: +[~,ndx] = natsort(ext,varargin{:}); +[~,ind] = natsort(nam(ndx),varargin{:}); +ndx = ndx(ind); +for k = max(len):-1:1 + idx = len>=k; + vec(~idx) = {''}; + vec(idx) = cellfun(@(c)c(k),pth(idx)); + [~,ind] = natsort(vec(ndx),varargin{:}); + ndx = ndx(ind); +end +% +% Return the sorted array and indices: +ndx = reshape(ndx,size(X)); +X = X(ndx); +% +end +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%natsortfiles \ No newline at end of file diff --git a/recognition/natsortfiles/natsortfiles_doc.m b/recognition/natsortfiles/natsortfiles_doc.m new file mode 100644 index 0000000..e5211c1 --- /dev/null +++ b/recognition/natsortfiles/natsortfiles_doc.m @@ -0,0 +1,94 @@ +%% NATSORTFILES Examples +% The function 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 +% 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 +% . +% +% For sorting a cell array of strings use +% . +% +%% 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'}; +sort(A) +natsortfiles(A) +%% 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) +%% Example with DIR and a Cell Array +% One common situation is using 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 all output arrays before the loop! +D = 'natsortfiles_test'; % directory path +S = dir(fullfile(D,'*.txt')); % get list of files in directory +N = natsortfiles({S.name}); % sort file names into order +for k = 1:numel(N) + fullfile(D,N{k}) +end +%% 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 +S = dir(fullfile(D,'*.txt')); % get list of files in directory +[~,ndx] = natsortfiles({S.name}); % indices of correct order +S = S(ndx); % sort structure using indices +for k = 1:numel(N) + S(k).name; + S(k).date; +end +%% 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'}; +sort(B) % '-' sorts before '.' +natsort(B) % '-' sorts before '.' +natsortfiles(B) % correct dictionary sort +%% 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'}; +sort(C) % Wrong numeric order. +natsort(C) % Correct numeric order, but longer before shorter. +natsortfiles(C) % Correct numeric order and dictionary sort. +%% 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'}; +sort(D) % Wrong numeric order, and '-' sorts before '\': +natsort(D) % correct numeric order, but longer before shorter. +natsortfiles(D) % correct numeric order and dictionary sort. +%% 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'}; +natsortfiles(E,'\d+(\.\d+)?') \ No newline at end of file diff --git a/recognition/show_example.m b/recognition/show_example.m new file mode 100644 index 0000000..9f8331c --- /dev/null +++ b/recognition/show_example.m @@ -0,0 +1,59 @@ +load('data.mat'); +%% show +sequence = 100:200; +subject = 1; +activity = 1; +samples =1; + + +example1 = data{1, 1, 1}(sequence, :)'; +example2 = data{1, 8, 1}(sequence, :)'; +example3 = data{1, 9, 1}(sequence, :)'; + + +figure(1); +subplot(211); +grid off; +imagesc(example1); +axis equal; +title ('The color map of activity ''ReSt'' from the first subject') +colormap('jet') +axis([1,100,1,25]); +colorbar; + +subplot(212); +grid off; +imagesc(example2); +axis equal; +title ('The color map of activity ''TuRi'' from the first subject') +colormap('jet') +axis([1,100,1,25]); +colorbar; + +figure (2) +subplot(311); +grid off; +imagesc(example1); +axis equal; +title ('The color map of activity ''ReSt'' from the first subject') +colormap('jet') +axis([1,100,1,25]); +colorbar; + +subplot(312); +grid off; +imagesc(example2); +axis equal; +title ('The color map of activity ''TuRi'' from the first subject') +colormap('jet') +axis([1,100,1,25]); +colorbar; + +subplot(313); +grid off; +imagesc(example3); +axis equal; +title ('The color map of activity ''Up'' from the first subject') +colormap('jet') +axis([1,100,1,25]); +colorbar; \ No newline at end of file diff --git a/recognition/show_results.m b/recognition/show_results.m new file mode 100644 index 0000000..5785a96 --- /dev/null +++ b/recognition/show_results.m @@ -0,0 +1,90 @@ +function [accuracy_kcc, accuracy_dtw] = show_results(filename) + addpath('matrix2latex') + if nargin < 1 + clear + results = load('results.mat'); + else + load(filename); + end + + fusion_matrix_kcc = zeros(65); + fusion_matrix_dtw = zeros(65); + + response = results.response; + distance = results.distance; + + %% show + for s = 1:size(response,1) + r = reshape(response(s,:,:),65,65); + d = reshape(distance(s,:,:),65,65); + if nargin < 1 + figure(1); + subplot(4,5,s); + + imagesc(r./max(r(:))) + axis off; + axis equal; + grid off; + colorbar; + + figure(2); + subplot(4,5,s); + + imagesc(d./max(d(:))); + axis off; + axis equal; + grid off; + colorbar; + end + + r(eye(size(r))~=0)=0; + [minvalue, idr] = max(r); + d(d==0)=inf; + [maxvalue, idd] = min(d); + + idx_kcc = sub2ind(size(fusion_matrix_kcc), 1:65, idr); + fusion_matrix_kcc(idx_kcc) = fusion_matrix_kcc(idx_kcc) +1; + + idx_dtw = sub2ind(size(fusion_matrix_dtw), 1:65, idd); + fusion_matrix_dtw(idx_dtw) = fusion_matrix_dtw(idx_dtw) +1; + end + + fusion_matrix_kcc(eye(size(fusion_matrix_kcc))~=0) = size(response,1); + fusion_matrix_dtw(eye(size(fusion_matrix_dtw))~=0) = size(distance,1); + if nargin < 1 + figure(3); + subplot(121); + imagesc(fusion_matrix_kcc./size(response,1)); + axis equal; + axis([1,65,1,65]); + colorbar; + grid off; + title('KCC'); + subplot(122); + imagesc(fusion_matrix_dtw./size(distance,1)); + axis equal; + colorbar; + axis([1,65,1,65]); + grid off; + title('DTW'); + end + accuracy_kcc = trace(sum_blocks(fusion_matrix_kcc, 5, 5))/sum(fusion_matrix_kcc(:)); + accuracy_dtw = trace(sum_blocks(fusion_matrix_dtw, 5, 5))/sum(fusion_matrix_dtw(:)); + + if nargin < 1 + fprintf('accuracy kcc: %f; dtw: %f', accuracy_kcc, accuracy_dtw); + end + + table_comparison = ... + [diag(sum_blocks(fusion_matrix_kcc, 5, 5)./200)*100,... + diag(sum_blocks(fusion_matrix_dtw, 5, 5)./200)*100, results.time_use/65/65*1000*1000]; + + table_comparison = [table_comparison; mean(table_comparison)] + + matrix2latex(table_comparison, 'comparison_results.txt'); + + function out = sum_blocks(A, block_nrows, block_ncols) + out = squeeze(sum(reshape(sum(reshape(A,block_nrows,[])),... + size(A,1)/block_nrows,block_ncols,[]),2)); + end +end \ No newline at end of file