ref #6 peak detection implementiert, noch ohne prominence faktor von matlab. läuft aber gut

This commit is contained in:
toni
2017-12-08 17:07:01 +01:00
parent 366fb034a4
commit efa6f95972
2 changed files with 108 additions and 2 deletions

View File

@@ -3,6 +3,7 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.stream.IntStream;
/**
@@ -15,6 +16,9 @@ public class Main {
File[] listOfFiles = folder.listFiles();
Utils.ShowPNG windowRaw = new Utils.ShowPNG();
Utils.ShowPNG windowAuto = new Utils.ShowPNG();
Utils.ShowPNG windowPeaksX = new Utils.ShowPNG();
Utils.ShowPNG windowPeaksY = new Utils.ShowPNG();
Utils.ShowPNG windowPeaksZ = new Utils.ShowPNG();
// iterate trough files in measurements folder
for (File file : listOfFiles) {
@@ -78,10 +82,50 @@ public class Main {
windowAuto.set(plotCorr.draw());
//find peaks
LinkedList<Integer> peaksX = Utils.findPeaks(xAutoCorr, 50, 0.1f, 0, false);
double[] dPeaksXX = IntStream.range(0, peaksX.size()).mapToDouble(i -> (peaksX.get(i) - 1024)).toArray();//peaks.stream().mapToDouble(i->i).toArray();
double[] dPeaksXY = IntStream.range(0, peaksX.size()).mapToDouble(i -> (dXAuto[peaksX.get(i)])).toArray();
Plot plotPeaksX = Plot.plot(Plot.plotOpts().
title("Peak Detection on X").
legend(Plot.LegendFormat.BOTTOM)).
series("x", Plot.data().xy(rangeAuto, dXAuto), Plot.seriesOpts().color(Color.RED)).
series("Peaks", Plot.data().xy(dPeaksXX, dPeaksXY), Plot.seriesOpts().color(Color.CYAN).
marker(Plot.Marker.DIAMOND).line(Plot.Line.NONE));
windowPeaksX.set(plotPeaksX.draw());
LinkedList<Integer> peaksY = Utils.findPeaks(yAutoCorr, 50, 0.1f, 0, false);
double[] dPeaksYX = IntStream.range(0, peaksY.size()).mapToDouble(i -> (peaksY.get(i) - 1024)).toArray();//peaks.stream().mapToDouble(i->i).toArray();
double[] dPeaksYY = IntStream.range(0, peaksY.size()).mapToDouble(i -> (dYAuto[peaksY.get(i)])).toArray();
Plot plotPeaksY = Plot.plot(Plot.plotOpts().
title("Peak Detection on Y").
legend(Plot.LegendFormat.BOTTOM)).
series("x", Plot.data().xy(rangeAuto, dYAuto), Plot.seriesOpts().color(Color.RED)).
series("Peaks", Plot.data().xy(dPeaksYX, dPeaksYY), Plot.seriesOpts().color(Color.CYAN).
marker(Plot.Marker.DIAMOND).line(Plot.Line.NONE));
windowPeaksY.set(plotPeaksY.draw());
LinkedList<Integer> peaksZ = Utils.findPeaks(zAutoCorr, 50, 0.1f, 0, false);
double[] dPeaksZX = IntStream.range(0, peaksZ.size()).mapToDouble(i -> (peaksZ.get(i) - 1024)).toArray();//peaks.stream().mapToDouble(i->i).toArray();
double[] dPeaksZY = IntStream.range(0, peaksZ.size()).mapToDouble(i -> (dZAuto[peaksZ.get(i)])).toArray();
Plot plotPeaksZ = Plot.plot(Plot.plotOpts().
title("Peak Detection on Z").
legend(Plot.LegendFormat.BOTTOM)).
series("x", Plot.data().xy(rangeAuto, dZAuto), Plot.seriesOpts().color(Color.RED)).
series("Peaks", Plot.data().xy(dPeaksZX, dPeaksZY), Plot.seriesOpts().color(Color.CYAN).
marker(Plot.Marker.DIAMOND).line(Plot.Line.NONE));
windowPeaksZ.set(plotPeaksZ.draw());
//fill hols improve peaks
//estimate bpm between detected peaks
int dummyForBreakpoint = 0;
}

View File

@@ -5,6 +5,7 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class Utils {
@@ -97,7 +98,6 @@ public class Utils {
}
}
public static float sqr(float x) {
return x * x;
}
@@ -180,8 +180,70 @@ public class Utils {
return c;
}
//TODO: findPeaks
//TODO: findPeaks method identical to Matlab... with PeakProminence
/**
* Simple method for finding local maxima in an array
* @param data input
* @param width minimum distance between peaks
* @param threshold minimum value of peaks
* @param decayRate how quickly previous peaks are forgotten
* @param isRelative minimum value of peaks is relative to local average
* @return array of peaks
*/
public static LinkedList<Integer> findPeaks(float[] data, int width, float threshold, float decayRate, boolean isRelative) {
LinkedList<Integer> peaks = new LinkedList<>();
int maxp = 0;
int mid = 0;
int end = data.length;
float av = data[0];
while (mid < end) {
av = decayRate * av + (1 - decayRate) * data[mid];
if (av < data[mid])
av = data[mid];
int i = mid - width;
if (i < 0)
i = 0;
int stop = mid + width + 1;
if (stop > data.length)
stop = data.length;
maxp = i;
for (i++; i < stop; i++)
if (data[i] > data[maxp])
maxp = i;
if (maxp == mid) {
if (overThreshold(data, maxp, width, threshold, isRelative, av)){
peaks.add(new Integer(maxp));
}
}
mid++;
}
return peaks;
}
private static boolean overThreshold(float[] data, int index, int width,
float threshold, boolean isRelative,
float av) {
int pre = 3;
int post = 1;
if (data[index] < av)
return false;
if (isRelative) {
int iStart = index - pre * width;
if (iStart < 0)
iStart = 0;
int iStop = index + post * width;
if (iStop > data.length)
iStop = data.length;
float sum = 0;
int count = iStop - iStart;
while (iStart < iStop)
sum += data[iStart++];
return (data[index] > sum / count + threshold);
} else
return (data[index] > threshold);
}
@SuppressWarnings("serial")