display("functions") source("settings.m"); function files = getDataFiles(clsName, trainsetPerClass) global setDataDir; 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() #global trainsetPerClass; data = {}; data{1}.samples = getSamplesForClass("forwardbend", 9, 10, 0.95); data{2}.samples = getSamplesForClass("kneebend", 11, 10, 0.95); data{3}.samples = getSamplesForClass("pushups", 11, 10, 0.95); data{4}.samples = getSamplesForClass("situps", 8, 10, 0.95); data{5}.samples = getSamplesForClass("jumpingjack", 13, 10, 0.95); 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) global setWindowSize; pos = posMS / 10; #only full windows are accepted. if length(rawVec) <= pos+(setWindowSize/2)-1 win = []; else win = rawVec(pos-(setWindowSize/2):pos+(setWindowSize/2)-1,:); #100*10 ms is half the window size. 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) global setWindowSize; global setWindowSliding; windowedData = {}; for k = 1:numel(data) for j = 1:numel(data{k}.samples) #init winsAccelX = {}; winsAccelY = {}; winsAccelZ = {}; winsGyroX = {}; winsGyroY = {}; winsGyroZ = {}; winsMagnetX = {}; winsMagnetY = {}; winsMagnetZ = {}; winsAccelPCA = {}; winsGyroPCA = {}; winsMagnetPCA = {}; winsAccelMG = {}; winsGyroMG = {}; winsMagnetMG = {}; winEnd = length(data{k}.samples{j}.raw{1}) * 10; # *10ms winBuffer = ((setWindowSize/2)+1) * 10; for i = winBuffer:setWindowSliding:winEnd-winBuffer #steps for sliding/overlapping windows #accel winAccel = window(data{k}.samples{j}.raw{1}, i); winsAccelX = [winsAccelX winAccel(:,1)]; winsAccelY = [winsAccelY winAccel(:,2)]; winsAccelZ = [winsAccelZ winAccel(:,3)]; [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); winsGyroX = [winsGyroX winGyro(:,1)]; winsGyroY = [winsGyroY winGyro(:,2)]; winsGyroZ = [winsGyroZ winGyro(:,3)]; [coeff2, score2] = princomp(winGyro); winsGyroPCA = [winsGyroPCA score2(:,1)]; winGyroMG = getMagnitude(winGyro); winsGyroMG = [winsGyroMG winGyroMG]; #magnet winMagnet = window(data{k}.samples{j}.raw{3}, i); winsMagnetX = [winsMagnetX winMagnet(:,1)]; winsMagnetY = [winsMagnetY winMagnet(:,2)]; winsMagnetZ = [winsMagnetZ winMagnet(:,3)]; [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 = winsAccelX; #X windowedData{k}.samples{j}.raw{2}.wins = winsAccelY; #Y windowedData{k}.samples{j}.raw{3}.wins = winsAccelZ; #Z windowedData{k}.samples{j}.raw{4}.wins = winsGyroX; windowedData{k}.samples{j}.raw{5}.wins = winsGyroY; windowedData{k}.samples{j}.raw{6}.wins = winsGyroZ; windowedData{k}.samples{j}.raw{7}.wins = winsMagnetX; windowedData{k}.samples{j}.raw{8}.wins = winsMagnetY; windowedData{k}.samples{j}.raw{9}.wins = winsMagnetZ; windowedData{k}.samples{j}.raw{10}.wins = winsAccelPCA; windowedData{k}.samples{j}.raw{11}.wins = winsGyroPCA; windowedData{k}.samples{j}.raw{12}.wins = winsMagnetPCA; windowedData{k}.samples{j}.raw{13}.wins = winsAccelMG; windowedData{k}.samples{j}.raw{14}.wins = winsGyroMG; windowedData{k}.samples{j}.raw{15}.wins = winsMagnetMG; end end end function features = featureCalculation(data) global setAutocorrelationBinSize; global setPSDBinSize; 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}; #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, setAutocorrelationBinSize); #define bins for the data. binSize = abs(binCenter(end-1) - binCenter(end)); binEdges = linspace(binCenter(1)-(binSize/2), binCenter(end)+(binSize/2), setAutocorrelationBinSize+1); [binNumc, binIdx] = histc(autoCorr, binEdges); binMeans = getBinMean(autoCorr, binIdx, setAutocorrelationBinSize); #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), setPSDBinSize + 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 #statistical features windowMean = mean(currentWindow); windowSTD = std(currentWindow); #standard deviation windowVariance = var(currentWindow); windowKurtosis = kurtosis(currentWindow); #(ger. Wölbung) windowIQR = iqr(currentWindow); #interquartile range #put everything together classLabel = k; #what class? sampleLabel = j; #what sample? features = [features; sampleLabel, classLabel, binMeans, rms, psd, windowMean, windowSTD, windowVariance, windowKurtosis, windowIQR]; end end end end end function value = getBinMean(data, idx, numBins) #search for an idx == numBins+1. this index occurs if a value == lastEdge, thanks histc... isSix = find(idx == numBins+1); if isSix != 0 idx(isSix) = numBins; endif value = []; for i = 1:numBins flagBinMembers = (idx == i); binMembers = data(flagBinMembers); if length(binMembers) == 0 value(i) = 0; else value(i) = mean(binMembers); endif end end #triangular functions. (edges of the triangles; num fft values -> nfft.) function triFilter = getTriangularFunction(edges, nfft) global samplerateHZ; #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)/samplerateHZ); 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