2024.9.22 计划

项目部分

个人学习部分

总结

如果得到了声音的信号,可以经过处理用python绘制出来对应位置的热力图,这里采用随机生成的声音信号,代码如下:

import numpy as np
import matplotlib.pyplot as plt

# 常量定义
M_side = 16  # 使用4x4阵列
d = 0.1  # 麦克风之间的距离 (m)
c = 343  # 声速 (m/s)
N = 1000  # 采样点数
fs = 8000  # 采样频率 (Hz)
t = np.linspace(0, N / fs, N)  # 时间数组

# 定义更大的二维麦克风阵列的位置 (4x4平面阵列)
mic_positions = np.array([[i * d, j * d] for i in range(M_side) for j in range(M_side)])
M = mic_positions.shape[0]  # 总麦克风数量


# 每次生成随机位置和信号
def generate_random_signal():
    # 随机生成声源的二维平面位置
    true_x = np.random.uniform(0, 1)
    true_y = np.random.uniform(0, 1)

    # 随机生成信号频率 (200 Hz 到 2000 Hz)
    f = np.random.uniform(200, 2000)

    # 生成模拟的声源信号 s(t) (随机频率的正弦信号)
    s = np.sin(2 * np.pi * f * t)  # 正弦信号

    # 随机生成声源距离 (0.5米到2米)
    true_distance = np.random.uniform(1, 5)
    print(f"Generated random sound source at ({true_x:.2f}, {true_y:.2f}, {true_distance:.2f}) with frequency {f:.2f} Hz")

    return s, true_x, true_y, true_distance, f


# 生成麦克风阵列接收到的信号
def generate_received_signals(s, true_x, true_y, true_distance, f):
    X = np.zeros((M, N), dtype=complex)  # 麦克风阵列接收到的信号
    for m, pos in enumerate(mic_positions):
        # 计算每个麦克风到声源的距离
        distance = np.sqrt((true_x - pos[0]) ** 2 + (true_y - pos[1]) ** 2 + true_distance ** 2)

        # 引入距离衰减效应和相位延迟
        attenuation = 1 / (distance ** 2)  # 衰减因子
        delay = distance / c  # 计算相位延迟

        # 生成接收到的信号,并考虑衰减和延迟
        X[m, :] = attenuation * s * np.exp(-1j * 2 * np.pi * f * delay)
    return X


# 计算导向矢量函数,考虑平面上的 (x, y) 坐标和距离
def calculate_steering_vector(x, y, z, mic_positions, f, c):
    steering_vector = np.zeros(len(mic_positions), dtype=complex)
    for m, pos in enumerate(mic_positions):
        distance = np.sqrt((x - pos[0]) ** 2 + (y - pos[1]) ** 2 + z ** 2)
        steering_vector[m] = np.exp(-1j * 2 * np.pi * f * distance / c)
    return steering_vector


# 计算功率谱
def calculate_power_spectrum(steering_vector, R):
    return np.real(np.conjugate(steering_vector).T @ R @ steering_vector)


# 主函数:生成随机信号并计算热力图
def generate_heatmap():
    # 生成随机信号和位置、距离
    s, true_x, true_y, true_distance, f = generate_random_signal()

    # 生成麦克风阵列接收到的信号
    X = generate_received_signals(s, true_x, true_y, true_distance, f)

    # 加入噪声
    noise = 0.1 * np.random.randn(M, N)
    X += noise

    # 计算协方差矩阵 R
    R = (X @ X.conj().T) / N

    # 创建二维平面网格,定义扫描范围
    grid_size = 100  # 网格尺寸 (100x100)
    x_range = np.linspace(0, 1, grid_size)  # X 轴范围
    y_range = np.linspace(0, 1, grid_size)  # Y 轴范围
    power_map = np.zeros((grid_size, grid_size))

    max_power = -np.inf  # 初始化最大功率
    max_position = (0, 0)  # 初始化最大功率的位置

    # 扫描平面中的每个点 (x, y),假设声源在此点
    for i, x in enumerate(x_range):
        for j, y in enumerate(y_range):
            steering_vector = calculate_steering_vector(x, y, true_distance, mic_positions, f, c)
            power = calculate_power_spectrum(steering_vector, R)
            power_map[j, i] = power
            # 找到最大功率
            if power > max_power:
                max_power = power
                max_position = (x, y)

    # 归一化功率谱
    power_map = power_map / np.max(power_map)

    # 打印找到的声源位置和真实距离
    print(f"Estimated sound source position: {max_position} with true distance {true_distance:.2f} meters")

    # 绘制二维热力图
    plt.imshow(power_map, extent=[x_range.min(), x_range.max(), y_range.min(), y_range.max()], cmap='hot',
               origin='lower')
    plt.title(f'2D Sound Source Heatmap (Estimated Source at {max_position})')
    plt.colorbar(label='Power Spectrum')
    plt.show()


# 生成随机信号并绘制热力图
generate_heatmap()

同时考虑距离对于生成图片的影响,距离近的时候定位非常准确,产生的圆形范围较小,远的时候定位不够准确,圆形范围较大。
以下三张图分别以距离为0.31m, 1.31m, 4.31m作比较(位置为(0.34, 0.44)):
距离0.31m
距离1.31m
距离4.31m

posted on 2024-09-22 12:21  Laurance  阅读(1)  评论(0编辑  收藏  举报