通过在 MATLAB 中获取上下包络来封装信号
Encase signal by getting the upper and lower envelope in MATLAB
我有一个围绕某些值反弹的信号。我想封装来自上方和下方的信号,如下图所示:
如果信号只是增加或减少,使用 运行 maxima 脚本效果很好:
function [out] = rMax(X)
Y=X;
maximum=X(1);
for k=1:length(X)
if X(k)<=maximum
Y(k)=maximum;
else
maximum=X(k);
end
end
out=Y;
end
但是,当信号交替时,我不能再使用该方法了。有没有办法在 MATLAB 或 Mathematica 中实现这一点?
您可以根据需要将 movmax
and movmin
与适当的 window 尺码结合使用 n1
> n2
。 这两个功能是在R2016a中引入的。查看我的答案底部,找到在 R2016a 之前有效的自写替代品。
要获得上限,您可以使用:
xMax = movmax(x,[n1,n1]);
xMax = movmin(xMax,[n2,n2]);
对于下限,只需切换movmin
和movmax
:
xMin = movmin(x,[n1,n1]);
xMin = movmax(xMin,[n2,n2]);
结果可能如下所示:
如果您选择 n2=n1
,当数据 x
中出现峰值时,边界非常紧。如果您通过使 n2
小于 n1
来选择更大的差异,您将在峰值处获得更长的直线。一个副作用是,当信号从 1 跳到 -1 时,边界开始变远,反之亦然。如果 n1
选得太高,信号中 100 左右的一小部分将不会被提取。
这是生成上图的完整代码,其中包含一些与您问题中的情节匹配的样本数据。只需使用值 n1
和 n2
来查看它们的效果。
n1 = 20; % for first window
n2 = 18; % for second window
% generate sample data
t = 20:0.1:220;
x = -ones(size(t));
x(t>60&t<100) = 1;
x(t>105&t<135) = 1;
x(t>145&t<155) = 1;
x = x + 0.4*randn(size(x));
% get upper bounds
xMax = movmax(x,[n1,n1]);
xMax = movmin(xMax,[n2,n2]);
% get lower bounds
xMin = movmin(x,[n1,n1]);
xMin = movmax(xMin,[n2,n2]);
% draw figure for illustration
figure; hold on;
plot(t,x);
xlim([20,220]);
ylim([-3,3]);
plot(t,xMax,'r','LineWidth',1.1);
plot(t,xMin,'Color',[0,0.5,0],'LineWidth',1.1);
R2016a 之前
要在R2016a之前的MATLAB版本中拥有movmin
和movmax
的基本功能,我们可以实现自己的功能。因此,我们需要应用可以很容易实现的移动最小值(或移动最大值)。为了保持与 R2016a 中函数的兼容性,我们将实现第二个参数是标量且它是两个元素的向量的情况。这涵盖了以下类似于 here 的语法,但限制是 x
需要是向量。
y = movingmax(x,k)
y = movingmax(x,[kb kf])
这是替换 movmax
的 movingmax
的代码:
function y = movingmax(x,n)
if length(n) > 1
a=n(1); b=n(2);
else
b=floor((n-1)/2); a=b+mod(n-1,2);
end
s = size(x);
xp = [ones(a,1)*x(1);x(:);ones(b,1)*x(end)];
y = zeros(size(x));
for k = 1:length(x)
y(k) = max(xp(k:k+a+b));
end
y = reshape(y,s);
这是替换 movmin
的 movingmin
的代码:
function y = movingmin(x,n)
if length(n) > 1
a=n(1); b=n(2);
else
b=floor((n-1)/2); a=b+mod(n-1,2);
end
s = size(x);
xp = [ones(a,1)*x(1);x(:);ones(b,1)*x(end)];
y = zeros(size(x));
for k = 1:length(x)
y(k) = min(xp(k:k+a+b));
end
y = reshape(y,s);
我在 运行 maxima/minima 函数中添加了第二个条件
function [out] =rMin(X)
Y=X;
minimum=X(1);
for k=2:length(X)
if X(k)>=minimum
Y(k)=minimum;
else
minimum=X(k);
end
if X(k)>=(Y(k-1)+3)
minimum=X(k);
Y(k)=minimum;
end
end
out=Y;
end
我明白了,但在信号的某些部分仍然失败
我有一个围绕某些值反弹的信号。我想封装来自上方和下方的信号,如下图所示:
如果信号只是增加或减少,使用 运行 maxima 脚本效果很好:
function [out] = rMax(X)
Y=X;
maximum=X(1);
for k=1:length(X)
if X(k)<=maximum
Y(k)=maximum;
else
maximum=X(k);
end
end
out=Y;
end
但是,当信号交替时,我不能再使用该方法了。有没有办法在 MATLAB 或 Mathematica 中实现这一点?
您可以根据需要将 movmax
and movmin
与适当的 window 尺码结合使用 n1
> n2
。 这两个功能是在R2016a中引入的。查看我的答案底部,找到在 R2016a 之前有效的自写替代品。
要获得上限,您可以使用:
xMax = movmax(x,[n1,n1]);
xMax = movmin(xMax,[n2,n2]);
对于下限,只需切换movmin
和movmax
:
xMin = movmin(x,[n1,n1]);
xMin = movmax(xMin,[n2,n2]);
结果可能如下所示:
如果您选择 n2=n1
,当数据 x
中出现峰值时,边界非常紧。如果您通过使 n2
小于 n1
来选择更大的差异,您将在峰值处获得更长的直线。一个副作用是,当信号从 1 跳到 -1 时,边界开始变远,反之亦然。如果 n1
选得太高,信号中 100 左右的一小部分将不会被提取。
这是生成上图的完整代码,其中包含一些与您问题中的情节匹配的样本数据。只需使用值 n1
和 n2
来查看它们的效果。
n1 = 20; % for first window
n2 = 18; % for second window
% generate sample data
t = 20:0.1:220;
x = -ones(size(t));
x(t>60&t<100) = 1;
x(t>105&t<135) = 1;
x(t>145&t<155) = 1;
x = x + 0.4*randn(size(x));
% get upper bounds
xMax = movmax(x,[n1,n1]);
xMax = movmin(xMax,[n2,n2]);
% get lower bounds
xMin = movmin(x,[n1,n1]);
xMin = movmax(xMin,[n2,n2]);
% draw figure for illustration
figure; hold on;
plot(t,x);
xlim([20,220]);
ylim([-3,3]);
plot(t,xMax,'r','LineWidth',1.1);
plot(t,xMin,'Color',[0,0.5,0],'LineWidth',1.1);
R2016a 之前
要在R2016a之前的MATLAB版本中拥有movmin
和movmax
的基本功能,我们可以实现自己的功能。因此,我们需要应用可以很容易实现的移动最小值(或移动最大值)。为了保持与 R2016a 中函数的兼容性,我们将实现第二个参数是标量且它是两个元素的向量的情况。这涵盖了以下类似于 here 的语法,但限制是 x
需要是向量。
y = movingmax(x,k)
y = movingmax(x,[kb kf])
这是替换 movmax
的 movingmax
的代码:
function y = movingmax(x,n)
if length(n) > 1
a=n(1); b=n(2);
else
b=floor((n-1)/2); a=b+mod(n-1,2);
end
s = size(x);
xp = [ones(a,1)*x(1);x(:);ones(b,1)*x(end)];
y = zeros(size(x));
for k = 1:length(x)
y(k) = max(xp(k:k+a+b));
end
y = reshape(y,s);
这是替换 movmin
的 movingmin
的代码:
function y = movingmin(x,n)
if length(n) > 1
a=n(1); b=n(2);
else
b=floor((n-1)/2); a=b+mod(n-1,2);
end
s = size(x);
xp = [ones(a,1)*x(1);x(:);ones(b,1)*x(end)];
y = zeros(size(x));
for k = 1:length(x)
y(k) = min(xp(k:k+a+b));
end
y = reshape(y,s);
我在 运行 maxima/minima 函数中添加了第二个条件
function [out] =rMin(X)
Y=X;
minimum=X(1);
for k=2:length(X)
if X(k)>=minimum
Y(k)=minimum;
else
minimum=X(k);
end
if X(k)>=(Y(k-1)+3)
minimum=X(k);
Y(k)=minimum;
end
end
out=Y;
end
我明白了,但在信号的某些部分仍然失败