过滤器去除阻带中的禁止信息

信息处理 噪音 过滤
2022-02-05 18:00:51

是否有可能,以及如何做,扩展滤波器,将滤波器阻带中的信号转换为没有信息内容或至少与该频率范围内的输入信号零相关的噪声,只有通带中信号的任意小衰减?

为了可视化这一点,这是一个低通滤波器幅度频率响应,其等波纹阻带波瓣在 -72.5 dB 处达到峰值:

在此处输入图像描述

当过滤两个正弦调制频率扫描的总和(尝试解决问题的良好测试信号)时,生成的频谱图为:

在此处输入图像描述

我目前能想到的最好方法是在输入信号中添加一些噪声。在阻带波瓣的峰值处以比正弦曲线高 2.5 dB 的功率天真地添加三角噪声仍然显示频谱图中的正弦曲线:

在此处输入图像描述

在阻带 + 18.5 dB 处将噪声提高到峰值正弦波功率几乎完全隐藏了阻带上的正弦波:

在此处输入图像描述

但是噪音很大。我没有将噪声仅过滤到阻带,因为它需要额外的计算工作,并且因为在某些应用程序中信号会被抽取,并且无论如何噪声都会最终进入通带。

我也一直在考虑随机切换滤波器组的输出。切换将使阻带零点四处移动,同时在通带中引起最小的频率响应波动。但这种方法似乎是一条死胡同。如果输入是阻带内的复正弦曲线,那么为了消除输入和扰频器输出之间的相关性,滤波器组滤波器的频率响应之和需要在该频率处为零。如果按照我们的要求,对于所有阻带频率,这同时是可能的,那么还可以对滤波器组滤波器的脉冲响应求和,以获得具有均匀零阻带频率响应的滤波器。众所周知,这是不可能的。

也许不存在理想的方法。

绘图的 Python 代码:

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
c0 = signal.remez(8, [0, 0.25], [1], maxiter=100)
c = np.zeros(c0.size*2-1)
c[0::2] = c0
c[c0.size-1] = 1
c = c*0.5
freq, response = signal.freqz(c)
plt.plot(range(-c0.size+1, c0.size, 1), c, 'x')
plt.grid(True)
plt.show()
plt.plot(freq/(2*np.pi), 20*np.log10(np.abs(response)))
plt.grid(True)
plt.show()
print("Stop band ripple (dB):")
print(20*np.log10(np.abs(response[-1])))
delay_c = np.concatenate([np.zeros((c.size // 2)), [1], np.zeros((c.size // 2))])
freq, response = signal.freqz(delay_c - c)
plt.plot(range(-c0.size+1, c0.size, 1), delay_c - c, 'x')
plt.grid(True)
plt.show()
plt.plot(freq/(2*np.pi), 20*np.log10(np.abs(response)))
plt.grid(True)
plt.show()

N = 65536
f = 2
x = np.sin((lambda x: 0.5*np.pi*x - 0.5*np.sin(np.pi*x/N*f)*N/f)(np.arange(N)))
f = 5
x += np.sin((lambda x: 0.5*np.pi*x - 0.5*np.sin(np.pi*x/N*f)*N/f)(np.arange(N)))

def get_spectrogram(x):
  return signal.spectrogram(x, window=('gaussian', 64), scaling='spectrum', nperseg=1024, noverlap=1024-64, nfft=1024, detrend=False)

def plot_spectrogram(x):
  f, t, Sxx = get_spectrogram(x)
  plt.figure(figsize=(10,5))
  plt.pcolormesh(t, f, 10*np.log10(Sxx/np.max(Sxx) + 10e-100), shading='gouraud', cmap='pink', vmin=-112, vmax=0)
  plt.show()

f, t, Sxx = get_spectrogram(x);
plot_spectrogram(x)

y = np.convolve(x, c)
plot_spectrogram(y);

epsilon = 10**(-70/20)*np.sqrt(3) #sqrt(3) = sqrt(1/2)/sqrt(1/6) = sine rms / triangular noise rms
r = (np.random.uniform(size=y.size)-np.random.uniform(size=y.size))*epsilon
z = y + r
plot_spectrogram(z);

epsilon = 10**(-54/20)*np.sqrt(3)
z = y + (np.random.uniform(size=y.size)-np.random.uniform(size=y.size))*epsilon
plot_spectrogram(z);
1个回答

好吧,天真的方法当然是使用带通滤波器的互补(让允许的信息通过)作为带阻滤波器,并使用它来将不相关的噪声塑造成原始滤波器的阻带所在的位置. 然后,添加两者。

如果您不想这样做,例如因为您已经阅读过脏纸编码并意识到“攻击者”可以从过渡宽度推断出有关阻带噪声的信息,以恢复部分“白化”区域(这有点猜测——我不知道你的过滤器,你允许的信号/信息等),事情变得有点复杂。

一种出色的信息擦除器是与随机变量相乘。假设您在每个频率上的信号幅度是连续分布的,则乘法后的目标分布将是正常的,因为这是最高熵每方差即功率分布。

那么,问题是:我们如何将通带外的所有频率与(单独的)不相关的白色噪声相乘,而不是通带?好吧,我们首先将事物视为(离散)频域中的逐点乘法。好吧,这确实有效(除了“如何进入频域”的所有实际问题——这就是 OFDM 或 GFDM 可以解决的问题,但它对信号结构施加了限制)。所以,诀窍是

  1. 产生白噪声
  2. 过滤它(时域)或屏蔽它(频域)以仅影响带外区域
  3. 在频域中将其与信号逐点相乘
  4. (如有必要)转换回时域

有趣的是,步骤 2/3 建议您可以不用在频域中进行乘法运算,而是将您的信号与带限白噪声进行卷积并保留您感兴趣的信号——这感觉不对。我需要考虑一下。