问题
Is there some process that can determine / remove an unknown DC offset from a non-periodic discrete time signal?
The signal in in question has a sample rate of 25Hz and has harmonics of interest between 0.25 and 3 Hz.
I have tried using highpass filters mixed results, first I used a 10th order guassian with Fc = 0Hz, this did a good job of removing the offset but it severly attenuated the AC aswell although it did leave the signal shape intact, next I used a 168th order equilripple with a stopband at 0Hz and passband at 0.25Hz, the phase shift was too severe and the signal shape too distorted, the distortion could probably be reduced if the pass-band was brought down to 0.1Hz but this would just further increase the phase shift which I need to keep to the very minimum.
Before and after applying x - LPF(x), as suggested by Paul R
回答1:
I recommend using a notch filter at DC and using filtfilt to make it zero phase.
a = [1 , -0.98]; b = [1,-1];
y = filtfilt(b,a,x);
The closer the second value of a gets to -1 the narrower your notch will be.
回答2:
A DC offset means that some constant value was added to the signal (the name originates from adding a DC voltage to an analog AC signal). If the DC component is really constant (and not changing really slowly), then you don't have to design some high-order (and potentially unstable) high-pass filters - you can just subtract the average of your signal from the signal - which is, of course, a high-pass filter as well (averaging is a type of a low-pass, and '1 minus the average' is high-apss) --- but a very simple one.
If, on the other hand, you have a reason to believe that the DC component is not really a DC, but rather an AC with very low frequency, then you'd better average segments of your signal and not the signal as a whole, which is the same as using a low-pass filter with impulse response which is shorter then the length of the signal. In this case you have to make some assumptions about the "DC" component.
回答3:
Rather than implementing a high pass filter directly (which can be rather tricky for very low frequencies - you end up with a large number of coefficients and various issues with stability and passband ripple etc), you might instead want to consider implementing a low pass filter which will give you an estimate of the DC offset value, and then subtract this filtered offset from your signal, i.e. rather than:
y = HPF(x)
do this:
y = x - LPF(x)
The low pass filter can probably just be quite a simple filter with a relatively small number of terms. The big advantage of this implementation is that your higher frequency components should not have any unwanted artefacts due to phase, ripple, etc, since all you are doing is subtracting an almost stationary DC value from the samples.
The only potential downside is that if the DC offset is large you may have quite a long initial settling time before the estimate of the DC offset is accurate (although this is also true of any other implementation such as a direct high pass filter of course). If you have any a priori knowledge of what the offset value is likely to be (e.g. if it doesn't change very much from run to run, and you know the value from the previous run) then you can use this to optimise the settling time, by initialising the LPF state variables to a suitable value rather than 0.
回答4:
As others have said, to remove a DC offset, you can simply subtract the mean. Your signal does not need to be periodic, but it does need to be long enough to get a good estimate of the DC component.
If you still wish to go with a filtering approach, you can eliminate the severe distortion due to phase lag by using filtfilt. This function filters your timeseries once in the forwards direction and then once in the reverse direction, so that phase distortions cancel out.
回答5:
You can design a symmetric FIR filter as the low-pass filter that estimates the DC and then subtract the output from your input signal. This filter has constant group-delay.
来源:https://stackoverflow.com/questions/6994020/remove-unknown-dc-offset-from-a-non-periodic-discrete-time-signal