Forum: PC-Programmierung Mean Median Filter aus Libary extrahieren und nutzen (C++)


von Mann T. (mann_t)


Lesenswert?

Hallo,

aus diesem Projekt möchte ich den mean median filter extrahieren und 
selber nutzen: 
https://morf.lv/implementing-pulse-oximeter-using-max30100/ der Github 
Code hierzu: https://github.com/xcoder123/MAX30100

Die entsprechenden Stellen aus der Header und CPP Datei hab ich 
herauskopiert und kann diesen im VS kompellieren:

Header

```
#include <Arduino.h>
#include "SPO2_Filter.h"


float MAX30100::meanDiff(float M, meanDiffFilter_t* filterValues)


{
  float avg = 0;

  filterValues->sum -= filterValues->values[filterValues->index];
  filterValues->values[filterValues->index] = M;
  filterValues->sum += filterValues->values[filterValues->index];

  filterValues->index++;
  filterValues->index = filterValues->index % MEAN_FILTER_SIZE;

  if(filterValues->count < MEAN_FILTER_SIZE)
    filterValues->count++;

  avg = filterValues->sum / filterValues->count;
  return avg - M;
}
```

CPP

```

#include <Arduino.h>
#include "SPO2_Filter.h"



// DC removal //


float MAX30100::meanDiff(float M, meanDiffFilter_t* filterValues)


{
  float avg = 0;

  filterValues->sum -= filterValues->values[filterValues->index];
  filterValues->values[filterValues->index] = M;
  filterValues->sum += filterValues->values[filterValues->index];

  filterValues->index++;
  filterValues->index = filterValues->index % MEAN_FILTER_SIZE;

  if(filterValues->count < MEAN_FILTER_SIZE)
    filterValues->count++;

  avg = filterValues->sum / filterValues->count;
  return avg - M;
}
```

Wie nutze ich aber nun den Code für meinen Sketch? In meinem Basissketch 
habe ich einen Sensowert den ich über particlesensor.getIR oder getRed 
abrufe. Ich muss demnach ein Objekt der Klasse MAX30100 erzeugen und 
dann die Funktion meanDiff aufrufen? Und mein particlesensor.getIR() ist 
dann mein filterValues oder? Wie sieht es dann aber mit den anderen 
Variablen "float M, meanDiffFilter_t*" aus? Das eine ist ja mein Zeiger 
und das andere einfach eine Variable.

Also zuerst würde ich wie gesagt ein Objekt erzeugen:

MAX30100 meinObjekt;

Dann würde ich die Funktion aufrufen:

meinObjekt.meanDiff(float M, meanDiffFilter_t* filterValues);

den filter Values würde ich nun mit particleSensor.getRed() definieren:

particleSensor.meanDiff(float M, meanDiffFilter_t* 
particleSensor.getRed());

Was mache ich mit particleSensor.getRed() ? Oder ist das Blödsinn und 
ich muss eine Funktion "setfilterValues" erzeugen (in der CPP) und dann 
setze ich  den filterValues in der ino auf getRed?

Kennt sich da jemand aus?

Hier hab ich noch folgende Zeile gefunden:

```cpp
  float meanDiffResIR = meanDiff( dcFilterIR.result, &meanDiffIR);

```

PS: Sry wie füge ich Code hier ein?


Da wird mEn die Funktion meanDiff aufgerufen und einmal der Filterwert 
gesetzt (der zuvor durch den DC Folter ging)  und der &meanDiffIR ist 
ein Zeiger?

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Das hier ist ein Mittelwert Filter aber kein Median Filter.

So ein Mittelwert Filter ist aber eigentlich eine Fingerübung: Alten 
Wert durch neuen Wert überschreiben, index inkrementieren, aufsummieren, 
dividieren, feddich.

Fremden Code in C++ lesen muss man üben. Die Header Datei .h enthält 
hier wichtige Hinweise, z.B. was meanDiffFilter_t eigentlich ist.

Mann T. schrieb:
> Wie sieht es dann aber mit den anderen
> Variablen "float M, meanDiffFilter_t*" aus? Das eine ist ja mein Zeiger
> und das andere einfach eine Variable.

Gehe nochmals? durch die Anfänger Tutorials für C++ durch. M ist 
Variable, meanDiffFilter_t* filterValues ist ein Strukturzeiger auf eine 
meanDiffFilter_t Struktur.

Manchmal braucht man Filter für verschiedene Kanäle, dann würde man 
mehrere meanDiffFilter_t Strukturen (z.B. einen pro Kanal) vorhalten. 
Der verlinkte Code sieht das aus irgendeinem Grund vor, nutzt das aber 
nur für den IR Kanal.

von Oliver S. (oliverso)


Lesenswert?

Anfragen der Art: Hilfe !!! Ich habe irgendwo irgendwie irgend eine 
Software kopiert, und verstehe nur Bahnhof...

sind selten erfolgreich.

Eine einzelne Klasse aus einer ganze Bibliothek "auszubauen" und dann 
nur Teile davon zu benutzen kann durchaus anspruchsvoll sein. Du wirst 
dir den originalen Sourcecode anschauen müssen, um zu verstehen, wie das 
alles zusammenhängt.

Das wird niemand für dich machen.

Oliver

von Mann T. (mann_t)


Lesenswert?

Jim M. schrieb:
> Das hier ist ein Mittelwert Filter aber kein Median Filter.


Vielen Dank für deinen freundlichen und hilfreichen Beitrag! Dieser 
hilft mir bereits weiter! Aber vielleicht hättest du noch einen Tipp für 
mein Vorhaben?

Ich beschreibe mal was ich machen möchte und wie ich bisher vorgegangen 
bin. Ich habe 2 Signale, einmal ein Signal einer roten und einmal einer 
IR LED. Dabei handelt es sich um ein Signal das aus einem AC und einem 
DC Wert besteht. Zuerst entferne ich den DC Wert, hierzu sieht das 
Tutorial folgenden Code vor:

w = particleSensor.getRed() + 0.99 * w_old;
filtered_sensorvalue = w - w_old;
w_old = w;
Sensorwert = filtered_sensorvalue;

Einen alternativen Weg bin ich dadurch gegangen, dass ich für ein 
Zeitfenster von einigen Sekunden meine Werte zusammengezählt habe und 
danach durch die Anzahl der Messungen durchgerechnet. Danach habe ich 
meinen Mittelwert.

Anschließend sammle ich meinen temporären Maximalwert. Solange der 
Sensorwert größer ist als der gespeicherte temporärer Maximalwert und 
mein Signal positiv ist, solange ist der Sensorwert mein temporärer 
Maximalwert. Wird mein Sensorwert negativ, so ist der letzte temporäre 
Maximalwert mein positiver Peak. Gleiches mache ich nun auch im 
negativen Zyklus. Nachdem ich einen Peakmax und einen Peakmin habe ziehe 
ich den Peakmin vom Peakmax ab und müsste nun meinen AC Wert pro Zyklus 
haben. Zudem sammle ich im positiven Zyklus meinen Maximalwert des 
reinen Signals (ohne DC Filter) und ziehe dann den AC Wert vom 
Maximalwert ab, um dadurch zu meinem DC Wert zu gelangen.

Anschließend merke ich mir wann meine Programm den positiven Zyklus 
beginnt und wenn der negative endet und habe damit meine Zeit eines 
Pulses. 1 Minute durch diesen Wert ist dann mein Puls.

Den Code dazu kann ich noch posten, das wäre jedenfalls aktuell meine 
Lösung. Was denkst du dazu? Um bessere Werte zu ermitteln benötige ich 
noch Filter.

Ich werde alles schön zusammenschreibe und mit Bilder bzw kurzen Videos 
dokumentieren. Über jede Hilfe wäre ich sehr dankbar!

von Mann T. (mann_t)


Lesenswert?

Oliver S. schrieb:
> Anfragen der Art: Hilfe !!! Ich habe irgendwo irgendwie irgend eine
> Software kopiert, und verstehe nur Bahnhof...
>
> sind selten erfolgreich.
>
> Eine einzelne Klasse aus einer ganze Bibliothek "auszubauen" und dann
> nur Teile davon zu benutzen kann durchaus anspruchsvoll sein. Du wirst
> dir den originalen Sourcecode anschauen müssen, um zu verstehen, wie das
> alles zusammenhängt.
>
> Das wird niemand für dich machen.
>
> Oliver

Ich bin C++ Anfänger und der Code den ich kopiert habe arbeitet bspw mit 
Zeigern, ist nicht so, dass ich mir den Code nicht angeschaut habe. Den 
anderen Filter habe ich bereits erfolgreich "ausgebaut". Wobei ich auch 
für alle alternativen Filter/ Ideen offen bin. Manchmal sieht ein Profi 
sofort um welchen Filter es sich handelt/ welche besser sind etc pp und 
als Anfänger plagt man sich Tage damit. :)

: Bearbeitet durch User
von Purzel H. (hacky)


Lesenswert?

Aber die Funktionalitaet eines Medianfilters ist begriffen ?

Median uber wieviele Punkte ? Weshalb ?

Falls das alles klar ist, ist's schnell selbst geschrieben.

Hint, einen Medianfilter verwendet man wenn die Messreihe Ausreisser hat 
welche einen anderen Filter unpassend beeinflussen

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.