FIltering out chaotic noise from breathing sensor signal

49 Views Asked by At

I've got a signal from a respiratory sensor (chest strap, piezo sensor) and I need to extract (live) the breath-per-minute value. Now for a nice steady signal this is not such a problem, the problem occurs when unexpected noise enters the signal such as when the participant starts moving his torso and/or arms. Simply removing the signal introduced by the movements is not possible (like via high/low pass filter) as at least a part of the movement signal falls right into the expected range of the breathing. So I would like to detect breathing rates between 5 and 25 breaths per minute. Or wavelengths between 2.4-12 seconds (or 0.42 to 0.083Hz). The sensor is set to sample at 100Hz.

raw The first image (raw) shows the raw data. Horizontal axis is in ticks (each = 0.01s). As you can see the first 40 seconds or so the signal is reasonably okay. Then (between 45 and 60 seconds) arms where moved slowly. Then a short period of standing still (65-75s) and then the torso was rotated back and forth (80-95s), then a short period of standing still (95-115s) and finally (115-end) both arms and torso where moving (slowly).

average My first step is a moving average (second image - avg). The window is 1s long and overlaps by 0.5s, resulting a new averaged value every 0.5 seconds.

I'm using a peak and valley detection, plus a minimum size of the peak/valley and a minimum distance of a new peak/valley from the 'zero', to calculate the breaths-per-minute value. Obviously when the movements are present the signal frequency increases, but as at least a good part of the frequencies introduces by the movement fall within the allowed breathing rates, I'm at a loss of how to 'clean up' the signal further to get more accurate frequencies during any movements.

For reference I've included a third image (prc) with the breaths-per-minute plotted processed breath p min

Any suggestion is of course very welcome!

Marco

I looked into FFT, but a quick look seemed to indicate that my raw and averaged signals are not easily suited to use FFT. The range of frequencies it detects is huge. Alternative stuff like zero-crossing do not remove the issue.

1

There are 1 best solutions below

0
JonasH On

Your moving average is a form of low pass filtering, but a fairly poor one. Filter design is a fairly complex topic, but you need to consider the frequency response.

This site seem to provide a good tool to compute filter kernels. A moving average of 100 samples will have a response like this:

Moving average frequency response

By selecting a bandpass or low pass filter we can create filter kernels with much nicer looking frequency responses (0.1-0.4hz):

bandpass frequency response Note that I had to reduce the sampling frequencies to make the calculator produce values for such low frequencies, since 100hz sampling rate is ridiculous overkill if the highest frequency you want is 0.42hz.

This produces a filter kernel with a bunch of values. You can apply this in the time domain by convolution of the filter with your signal. You can also do it in the frequency domain by using an fft, this should be faster, but is probably overkill if you have a decent CPU.

This type of finite impulse response (FIR) filters require a (ring) buffer to use, so output will be delayed. There are also Infinite Impulse Response filter, but I remember little of these, other than that they are more complex to design. I would recommend further study if this is of interest.

Note that simple filtering might not be enough to get a good signal. You may want to try to detect when the patient is moving and just ignore all results during these periods. Possibly by looking at the noise the band-pass filter removed. You could possibly also make assumptions like "breathing frequency change slowly" or perhaps "in distinct steps", to further help provide better filtering/detection.