Files
HandyGames/toni/octave/functions.m

247 lines
8.0 KiB
Matlab

display("functions")
function files = getDataFiles(clsName, trainsetPerClass)
setDataDir = "/home/toni/Documents/handygames/HandyGames/daten/";
dir = strcat(setDataDir, clsName, "/");
lst = readdir(dir);
files = {};
cnt = 0;
for i = 1:numel(lst)
filename = lst{i};
if (regexp(filename, ".m$")) # use only files ending with .m
file = strcat(dir, filename);
files = [files file];
++cnt;
if (cnt >= trainsetPerClass) # use only x input files
break;
endif
endif
end
end
function samples = getSamplesForClass(clsName, trainsetPerClass, start, percent)
files = getDataFiles(clsName, trainsetPerClass); #load Data files - thanks franke
samples = {};
start = start / 10; #start is given in ms and our raw input data has an fixed update-intervall of 10ms
for i = 1 : numel(files)
source(files{i});
lengthSamples = length(Magnet); # length/number of all available samples
pEnd = lengthSamples * percent; # how many samples do we want?
raw = {Gyro(start:pEnd,:), Accel(start:pEnd,:), Magnet(start:pEnd,:)}; # create cell array of the wanted samples
samples{i}.raw = raw; # write them into cell array for each Class
end
display(strcat("training data for '", clsName, "': ", num2str(length(samples)), " samples"));
end
function data = getRawTrainData(trainsetPerClass)
data = {};
data{1}.samples = getSamplesForClass("forwardbend", trainsetPerClass, 10, 0.9);
data{2}.samples = getSamplesForClass("kneebend", trainsetPerClass, 10, 0.9);
data{3}.samples = getSamplesForClass("pushups", trainsetPerClass, 10, 0.9);
data{4}.samples = getSamplesForClass("situps", trainsetPerClass, 10, 0.9);
data{5}.samples = getSamplesForClass("jumpingjack", trainsetPerClass, 10, 0.9);
end
function plotData(data,outPath)
for k = 1:numel(data)
for j = 1:numel(data{k}.samples)
for i = 1:numel(data{k}.samples{j}.raw)
mat = data{k}.samples{j}.raw{i};
#subplot(6, 3, idx);
plot(mat);
legend("x","y","z");
print( gcf, '-dpng', fullfile(outPath, sprintf('img_%d_%d_%d.png', k, j, i) ) );
end
end
end
end
function filteredData = filterData(data)
pkg load signal;
filteredData = {};
for k = 1:numel(data)
for j = 1:numel(data{k}.samples)
for i = 1:numel(data{k}.samples{j}.raw)
mat = data{k}.samples{j}.raw{i};
[b, a] = butter(16, 0.2);
filteredData{k}.samples{j}.raw{i} = filtfilt(b, a, mat); #filtfilt extends the signal at beginning so we have no phaseshift
end
end
end
end
function win = window(rawVec, posMS)
pos = posMS / 10;
#check if out of bounce, if yes- fill with zeros
#the last windows are sometimes filled with a lot of zeros... this could cause problems
if length(rawVec) <= pos+100-1
#win = rawVec(pos-100:length(rawVec),:);
#fillOut = zeros((pos+100-1) - length(rawVec), 3);
#length(fillOut)
#win = [win; fillOut];
win = [];
else
win = rawVec(pos-100:pos+100-1,:); #100*10 ms is half the window size. that is 2s for each window.
endif
end
function out = getMagnitude(data)
out = [];
for i = 1:length(data)
tmp = sqrt(data(i,1)^2 + data(i,2)^2 + data(i,3)^2);
out = [out; tmp];
end
end
function windowedData = windowData(data)
windowedData = {};
for k = 1:numel(data)
for j = 1:numel(data{k}.samples)
winsAccel = {};
winsGyro = {};
winsMagnet = {};
winsAccelPCA = {};
winsGyroPCA = {};
winsMagnetPCA = {};
winsAccelMG = {};
winsGyroMG = {};
winsMagnetMG = {};
winEnd = length(data{k}.samples{j}.raw{1}) * 10; # *10ms
for i = 1010:200:winEnd-1010 #200ms steps for sliding/overlapping windows
#accel
winAccel = window(data{k}.samples{j}.raw{1}, i);
winsAccel = [winsAccel winAccel];
[coeff1, score1] = princomp(winAccel);
winsAccelPCA = [winsAccelPCA score1(:,1)]; #choose the first axis (eigvec with the biggest eigvalue)
winAccelMG = getMagnitude(winAccel);
winsAccelMG = [winsAccelMG winAccelMG];
#gyro
winGyro = window(data{k}.samples{j}.raw{2}, i);
winsGyro = [winsGyro winGyro];
[coeff2, score2] = princomp(winGyro);
winsGyroPCA = [winsGyroPCA score2(:,1)];
winGyroMG = getMagnitude(winGyro);
winsGyroMG = [winsGyroMG winGyroMG];
#magnet
winMagnet = window(data{k}.samples{j}.raw{3}, i);
winsMagnet = [winsMagnet winMagnet];
[coeff3, score3] = princomp(winMagnet);
winsMagnetPCA = [winsMagnetPCA score3(:,1)];
winMagnetMG = getMagnitude(winMagnet);
winsMagnetMG = [winsMagnetMG winMagnetMG];
end
#write back data
windowedData{k}.samples{j}.raw{1}.wins = winsAccel;
windowedData{k}.samples{j}.raw{2}.wins = winsGyro;
windowedData{k}.samples{j}.raw{3}.wins = winsMagnet;
windowedData{k}.samples{j}.raw{4}.wins = winsAccelPCA;
windowedData{k}.samples{j}.raw{5}.wins = winsGyroPCA;
windowedData{k}.samples{j}.raw{6}.wins = winsMagnetPCA;
windowedData{k}.samples{j}.raw{7}.wins = winsAccelMG;
windowedData{k}.samples{j}.raw{8}.wins = winsGyroMG;
windowedData{k}.samples{j}.raw{9}.wins = winsMagnetMG;
end
end
end
function features = featureCalculation(data)
features = [];
for k = 1:numel(data)
for j = 1:numel(data{k}.samples)
for i = 1:numel(data{k}.samples{j}.raw)
for m = 1:numel(data{k}.samples{j}.raw{i}.wins)
currentWindow = data{k}.samples{j}.raw{i}.wins{m};
currentWindow = currentWindow(:,1);
#autocorrelation on window. split into 5 evenly spaced bins (frequencies are evenly spaced, not number of values ;) ) and calculate mean of bin.
[autoCorr] = xcorr(currentWindow);
[binNum, binCenter] = hist(autoCorr, 5); #define 5 bins for the data.
binSize = abs(binCenter(end-1) - binCenter(end));
binEdges = linspace(binCenter(1)-(binSize/2), binCenter(end)+(binSize/2), 6);
[binNumc, binIdx] = histc(autoCorr, binEdges);
binMeans = getBinMean(autoCorr, binIdx, 5);
#calculate the root-mean-square (RMS) of the signal
rms = sqrt(mean(currentWindow.^2));
#power bands 0.5 to 25hz (useful if the windows are greater then 4s and window sizes to 256, 512..)
[powerBand, w] = periodogram(currentWindow); #fills up fft with zeros
powerEdges = logspace(log10(0.5), log10(25), 10 + 2); #logarithmic bin spaces for 10 bins
triFilter = getTriangularFunction(powerEdges, length(powerBand)*2 - 2);
for l = 1:numel(triFilter)
filteredBand = triFilter{l} .* powerBand;
psd(l) = sum(filteredBand); #sum freq (no log and no dct)
end
#put everything together
classLabel = k; #what class?
features = [features; classLabel, binMeans, rms, psd];
end
end
end
end
end
function value = getBinMean(data, idx, numBins)
value = [];
for i = 1:numBins
flagBinMembers = (idx == i);
binMembers = data(flagBinMembers);
# if length(binMembers) == 0
# idx
#data
# input = 'balala'
#endif
value(i) = mean(binMembers);
end
end
#triangular functions. (edges of the triangles; num fft values -> nfft.)
function triFilter = getTriangularFunction(edges, nfft)
#get idx of the edges within the samples. thanks to fft each sample represents a frequency.
# idx * samplerate / nfft = hertz of that idx
for i = 1:length(edges)
edgesByIdx(i) = floor((nfft + 1) * edges(i)/100); #100hz is the samplerate
end
#generate the triangle filters
triFilter = {};
for i = 1:length(edgesByIdx)-2
diffCnt = edgesByIdx(i+2) - edgesByIdx(i) + 1;
tmp = zeros(nfft/2 + 1, 1);
triVec = triang(diffCnt);
tmp(edgesByIdx(i):edgesByIdx(i+2)) = triVec;
triFilter{i} = tmp;
end
end