Be able to Detect Breathing

Hi
I dont have a great deal of experiance in matlab and would like some advice on detecting breathing,the samples taken in the figures attached are raw ADC inputs to matlab with no filtering , is there firstly something I could do to improve the waveforms? (pre filtering)
Also what is the best method (most reliable) to detect there is breathing and the rate of the breathing.
figures attached baseline(no one on the bed), Breathing (normal) and breathing2(shallow)
Thank you in advance for any help you can offer.
Kind Regards
David

 Accepted Answer

Mathieu NOE
Mathieu NOE on 27 May 2021
hello David
yes you can clear tell that the bed is not empty and that someone is actually breathing by either saying the time signal has amplitude above 100 (so let's compute a smoothed rectified version of this signal) , this can be also observed in the frequency spectrum has you have peaks showing up between 0.1 and 1 Hz
to compite the rate of breathing you can either pick the highest amplitude peak in the fft spectrum (and find it's corresponding frequency) or you can compute the period between two zero crossing values (works also with a non zero threshold) as example attached shows
hope it helps
all the best

14 Comments

Hi Mathieu
Thank you for responding to my question.
I have downloaded your files and tried them, they look promising. The only problem is they dont seem to work with my Data, firstly after running I get :
Warning: Ignoring extra legend entries.
> In legend>process_inputs (line 602)
In legend>make_legend (line 334)
In legend (line 278)
In microwave (line 118)
Warning: Ignoring extra legend entries.
It displays the Data but not the crosses I have attached my most recent Data File please can you take a look.
Kind Regards
David
hello again
here no problem with my R2020b
this is my code and the output : ( x axis in samples not in seconds as sampling rate is unknown to me)
clc
clearvars
load('Raw_Data.mat')
y = double(raw_ad_data_sine); % conversion to double
n=length(y);
x=(1:n);
threshold = 0.5; % your value here
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(y,x,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
% ind => time index (samples)
% t0 => corresponding time (x) values
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
figure(1)
plot(x,y,t0_pos,s0_pos,'+r',t0_neg,s0_neg,'+g','linewidth',2,'markersize',12);grid on
legend('signal','positive slope crossing points','negative slope crossing points');
HI Mathieu
Thanks for this help its been invaluable, I guess I am not calculating the correct X axis can you please show me how to display the correct timing on my sample, the sample rate is 0.01 number of samples 6000
Thank you once again
Kind regards
David
No problem
just to understand, when you say sample rate is 0.01 , so between two samples we have dt = 100 seconds ?
now this is an improved version of my code, assuming between two samples we have dt = 100 seconds
I added some high frequency filtering to avoid the zero crossing function to be "fooled" by the noise
then I computed the time interval between succesive positive slope crossing points (therefore you can get the frequency too
I have the feeling I don't have the right sampling rate here , 100 seconds between two samples seems very long for me
i also lifted the threshold to 100, so when there is no signal you would get no points
clc
clearvars
load('Raw_Data.mat')
y = double(raw_ad_data_sine); % conversion to double
n=length(y);
dt = 100;
x=(1:n)*dt;
threshold = 100; % your value here
% remove first some high frequency noise
yy = smoothdata(y,'gaussian',10);
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(yy,x,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
% ind => time index (samples)
% t0 => corresponding time (x) values
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
figure(1)
plot(x,yy,t0_pos,s0_pos,'+r',t0_neg,s0_neg,'+g','linewidth',2,'markersize',12);grid on
legend('signal','positive slope crossing points','negative slope crossing points');
xlabel('Time (s)');
% let's compute the period between crossing points , then frequency
period_pos = diff(t0_pos); % seconds
freq_pos = 1./period_pos; % Hz
figure(2)
plot(t0_pos(2:end),period_pos,'+r','linewidth',2,'markersize',12);grid on
xlabel('Time (s)');
ylabel('period (s)');
figure(3)
plot(t0_pos(2:end),freq_pos,'+r','linewidth',2,'markersize',12);grid on
xlabel('Time (s)');
ylabel('Frequency (Hz)');
Hi Mathieu
Thank you for your excellent help I have the code working now, I do have a couple of questions on the raw data file all of the frequency should almost be the same I think where the peaks are longer will be the time constant on the capacitors at this frequency ie charging and discharging is there any way to clean these up a little in Matlab.
Also what is the best way with the information in period_pos and freq_pos to basically say there is a xx% chance of breathing.
But once again thank you for your great help
Kind Regards
David
hi David
I coud add a bit of stopband or bandpass filtering to remove the unwanted frequencies
what is the frequency range for the capacitors (very low I suppose) ?
what is the frequency range for normal breathing ?
Hi Mathieu
The electronic high pass is 0.1 and the low pass is 0.45 breathing is around 0.15 to 0.4 hertz.
Thanks for your help on this
Kind Regards
David
So I made some mods in the code :
  • added a bandpass filter to remove signal outside the specified range
  • BTW , my sampling rate was incorrect so I changed that too
  • I also changed my crossing_V7 subfunction so that the incoming signal is completely "flat" , no crossing point data can be found so you get empty output : this is the situation when no breathing signal is present
  • I added a histogram count so you can tell how many times at which frequencies the signal crossed the threshold value; again, falt signal will genrerate empty data and plot (try it)
attached the updated codes
Hi Mathieu
Thank you for your excellent help, is there any way we can use the negative going wave forms as well?
Kind Regards
David
Hi Mathieu
I decided to put a xtal locked 250m Hertz signal in to test the script, whilst the FFT lock perfectly can you please take a look at the histagram it doesnt seem to be accurate?.
Kind Regards
David
hello
see the mods below , same frequency resolution now and same x axis span
axisHandleCh5 = subplot(5,1,5);
% h = histogram(freq_pos,"BinWidth",0.05)
h = histogram(freq_pos,"BinWidth",mean(diff(f_axis)))
h.BinLimits = [0 1];
xlabel('Frequency (Hz)');
ylabel('Counts');
Great thanks for all your help
my pleasure !

Sign in to comment.

More Answers (0)

Products

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!