專案部分
個人學習部分
總結
如果得到了聲音的訊號,可以經過處理用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