使用可听声纳的物体检测

信息处理 Python 匹配过滤器 线性啁啾 声纳 物体检测
2022-02-14 23:33:28

我目前正在开展一个项目,该项目使用一些非常强大的 PreSonus PM-2 麦克风,使用距离桌面扬声器约 1 到 2 m 的声纳(可听)在 60 度角扇区内识别环境中物体的位置和角度和一个百灵达 UMD404HD。

这是在带有 Python3.6 解释器的 PyCharm 中。使用 Audacity 进行同时录制,同时播放下图中的啁啾声:

6000 到 8000 Hz 之间的啁啾,持续时间 0.003

以下是我在距离声源约 75 厘米处放置角反射器获得的结果(录音、FFT、单面 FFT):

记录、FFT、单面 FFT

下一步是应用匹配滤波器来去除所有不需要的频率并识别来自角反射器的回波。这是下一个数字:

在此处输入图像描述

下面是我用来产生这样的代码:

import numpy as np
import matplotlib.pyplot as plt
import scipy
from scipy.signal import hilbert, chirp, windows
import scipy.io.wavfile as wavfile
from scipy.fftpack import fft
from scipy.signal import butter, lfilter
from scipy.signal import freqz

def generateChirp():
    print("Generating Chirp...\n")
    duration = .003
    fs = 44100.0
    samples = int(fs * duration)
    t = np.arange(samples) / fs

    signalC = chirp(t, 6000.0, t[-1], 8000.0)
    signalWinHann = np.multiply(signalC, windows.hann(signalC.shape[0]))

    #signalC *= (1.0 + 0.5 * np.sin(2.0 * np.pi * 3.0 * t))
    #analytic_signal = hilbert(signalC)
    #amplitude_envelope = np.abs(analytic_signal)

    signalWinHann = np.flipud(signalWinHann)
    plt.plot(signalWinHann, label='signal')
    plt.xlabel("Time (samples)")
    plt.ylabel("Amplitude")
    plt.title("Chirp")
    #plt.plot(t, amplitude_envelope, label='envelope')
    plt.show()
    wavfile.write("audioHann.wav", 44100, signalWinHann)

    print("Chirp Generated.\n")
    return t, fs, signalWinHann

def analyzeRecording():
    print("Analyzing Signal...\n")
    # Read the audio files data and sampling rate recorded
    fs_rate, signalC = wavfile.read(r"75cmcorner.wav")
    print ("Frequency of Sample: ", fs_rate)
    # The number of channels as per the .WAV file
    numOfChannels = len(signalC.shape)
    print("Channels: ", numOfChannels)
    # If there is two channels we read them both and sum them
    if numOfChannels == 2:
        signalC = signalC.sum(axis=1) / 2
    # Store the amount of data points in signal
    samplesOfSignal = signalC.shape[0]
    print("Number of samples in the signal: ", samplesOfSignal)
    # Get the length of the recorded signal
    lengthInSec = samplesOfSignal / float(fs_rate)
    print("Length of signal in seconds: ", lengthInSec)
    # Time step is inverse of Frequency Sampling rate
    Tsample = 1/fs_rate
    print("Sampling Timesteps: ", Tsample)
    # Time Vector
    t = np.arange(0, lengthInSec, Tsample)

    # Compute FFT to get frequency components of signal
    FFT = abs(fft(signalC))
    # Get single sided FFT of the signal
    FFT_side = FFT[range(samplesOfSignal//2)]
    Freqs = scipy.fftpack.fftfreq(signalC.size, t[1]-t[0])
    # One side frequency range
    Freqs_Side = Freqs[range(samplesOfSignal//2)]
    print("\nAnalyzing Signal Completed.\n")

    # Plot the Actual Signal
    plt.subplot(311)
    p1 = plt.plot(t, signalC, "g")
    plt.xlabel('Time')
    plt.ylabel('Amplitude')

    # Plot the FFT of the Signal
    plt.subplot(312)
    plt.plot(Freqs, FFT, "r")
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Amplitude')

    # Plot only the one side of the FFT Spectrum
    plt.subplot(313)
    p3 = plt.plot(Freqs_Side, abs(FFT_side), "b") # plotting the positive fft spectrum
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Amplitude')

    plt.show()
    return signalC, FFT_side

def matchedFilter(signalRec, signalWinHann, FFT_side):
    print("Applying Matched Filter...\n")

    signalMF = (np.abs(np.convolve(hilbert(signalWinHann), hilbert(signalRec), mode='valid')))
    padding = np.zeros(len(signalRec)//2)
    signalMF = np.concatenate((padding, signalMF, padding))
    print("Maximum peak at: " + str(signalMF.argmax()))
    plt.plot(signalMF, "m")
    plt.xlabel('Samples?')
    plt.ylabel('Amplitude')
    plt.show()
    print("\nMatched Filter Applied.\n")

    return

if __name__ == '__main__':
    # Generate a Chirp
    t, fs, signalWinHann = generateChirp()
    # Analyze recorded sound
    signalRec, FFT_side = analyzeRecording()
    # Apply matched filter.
    matchedFilter(signalRec, signalWinHann, FFT_side)

我不确定我是否正确执行了匹配的滤波器步骤、啁啾声的生成、响度,以及啁啾声是否需要执行多次或只执行一次,或者之前是否需要 LPF/BPF我进行任何处理,例如 FFT。我在这里查看了这篇文章,并且正在努力获得结果,因为我似乎根本没有捡起任何物体。社区是否有任何指导来帮助解决这个问题?

非常感谢您以任何可能的方式提供帮助!

编辑:没有意识到环境也很重要,我现在附上了我的物理设置的图片。

正视图

顶视图

编辑:在你们的帮助和更多研究的帮助下,有一些变化!首先,我的麦克风和扬声器设置关闭,因为最佳配置如下,因为峰值是最佳捕获声音的地方:

更好的配置

其次,Peter K. 向我传达了一些关于啁啾的深刻知识,但尚未实施。我还意识到,包围啁啾会消除每一侧的能量,因此必须重新运行测试。

第三,我将匹配滤波器的方程式更改为:

def matchedFilter(signalRec, signalWinHann, FFT_side):
    print("Applying Matched Filter...\n")
    signalMF3 = np.abs(np.convolve(hilbert(signalRec), np.conj(np.flipud(hilbert(signalWinHann)))))
    padding = np.zeros(len(signalRec)//2)
    print("Maximum peak at: " + str(signalMF3.argmax()))
    plt.semilogy(signalMF3, color='blue', lw=2)
    plt.xlim(0, 2000)
    plt.xlabel('Range (m)')
    plt.ylabel('Amplitude')
    plt.show()
    aSignal = hilbert(np.abs(signalMF3))
    envelope = np.abs(aSignal)
    norm = envelope*44100 / (sum(envelope))
    print("\nMatched Filter Applied.\n")

    return norm

在对我的信号应用上述相同啁啾的以下运行后,我收到以下图表:

在此处输入图像描述

可以看出,在缩放之后,我正确地检测到了在不同距离处误差约为 5 厘米的物体。上图用于检测距离发射源 75cm 处的约 6cm 圆柱形物体。

第四,匹配滤波在从信号中滤除噪声方面被认为是“最佳”的,因此不需要像 LPF 或 BPF 这样的其他滤波器来正确获得正确的结果。

我在对象检测方面的下一步是使用来自两个麦克风的输入,使用称为 1 个发射器和 2 个接收器的多点定位方法来确定反射脉冲的角度。我希望能很好地接受这个,因为有必要获得对象的正确方位。

我应该分割来自每个信号的通道吗?我目前不确定?

非常感谢你们迄今为止的帮助!我希望这篇文章有一天能像你们帮助我一样帮助别人!

1个回答

我不确定这是您唯一的问题,但我认为您的“啁啾”还不够(啁啾的最大和最小频率相距不够远)。

正因为如此,你得到:

频率差小

其中顶部曲线是啁啾,中间曲线是 FFT,底部曲线是匹配滤波器输出。

我已经设置

f1 = 4000;
f2 = 4400;

在下面的 matlab 代码中执行此操作。

相反,如果您选择:

f1 = 4000;
f2 = 12000;

然后我得到:

频率分布更广

这在匹配滤波器的输出端显示了更清晰的脉冲。

阅读此页面以了解详细信息。


下面是matlab代码

T = 1000;
fs = 44100;
t = [0:T-1]/fs;

f1 = 4000;
f2 = 12000;

x = chirp(t,f1,t(T) , f2);
xg = x.*exp(-0.005*abs([0:T-1]-(T-1)/2).^2/T);
figure(1);
clf;
subplot(311);
plot(x);
hold on;
plot(xg,'r');
subplot(312);
plot(abs(fft(x)));
hold on;
plot(abs(fft(xg)),'r');
subplot (313);
plot(xcorr(x,x));
hold on;
plot(xcorr(xg,xg),'r');
axis([950 1050 -400 600])