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