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