Ithy Logo

如何使用Python實現4x4麥克風陣列的二維波束形成及實時Heatmap呈現

全面指南:從硬體設定到實時視覺化的完整步驟與示例程式碼

microphone array heatmap

主要重點

  • 麥克風陣列配置與信號採集 - 確保音訊數據的正確收集與前處理
  • 二維波束形成算法實現 - 使用延遲與總和方法增強目標方向信號
  • 實時Heatmap生成與可視化 - 利用Matplotlib動態呈現聲源分佈

1. 麥克風陣列配置與信號採集

1.1 硬體配置

您的麥克風陣列為4x4佈局,共16個麥克風,每個麥克風在水平與垂直方向上的間隔均為42mm。這樣的配置允許在多個方向上精確地捕捉音訊信號,為後續的波束形成奠定基礎。麥克風的位置對於波束形成算法的準確性至關重要,因此必須正確設定每個麥克風的坐標。

1.2 音訊數據採集

使用Python進行音訊數據的實時採集,可以利用

pyaudio

sounddevice

等庫。以下範例展示如何初始化音頻流並讀取數據:


import pyaudio
import numpy as np

# 音訊參數設定
CHUNK = 1024  # 每次讀取的樣本數
RATE = 44100  # 採樣率 (Hz)
CHANNELS = 16  # 麥克風通道數

# 初始化pyaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)
    

1.3 麥克風陣列幾何結構

定義麥克風的位置對於計算延遲至關重要。以下是麥克風陣列的幾何結構設定:


mic_positions = np.array([
    [0, 0], [0, 0.042], [0, 0.084], [0, 0.126],
    [0.042, 0], [0.042, 0.042], [0.042, 0.084], [0.042, 0.126],
    [0.084, 0], [0.084, 0.042], [0.084, 0.084], [0.084, 0.126],
    [0.126, 0], [0.126, 0.042], [0.126, 0.084], [0.126, 0.126]
])  # 單位:米
    

1.4 麥克風性能與校準

為了確保波束形成的準確性,所有麥克風必須經過校準。校準過程包括檢查每個麥克風的靈敏度、頻率響應和相位一致性。任何麥克風的不一致性都可能導致波束形成結果的偏差。

1.5 資料前處理

在進行波束形成之前,需要對音訊數據進行前處理,包括去除直流分量、應用高通或低通濾波器以消除不需要的頻率成分,以及對多通道信號進行標準化處理,以確保各通道信號的均衡。


2. 二維波束形成算法實現

2.1 波束形成基本原理

波束形成(Beamforming)是一種信號處理技術,用於通過麥克風陣列中的多個麥克風信號,通過調整各個信號的相位與幅度,來增強特定方向的聲音信號,同時抑制其他方向的噪聲。這樣可以精確地定位聲源方向並提升信噪比。

2.2 延遲與總和(Delay-and-Sum)波束形成

延遲與總和是一種基本的波束形成方法。其步驟如下:

  1. 計算延遲時間:根據麥克風陣列的幾何結構和目標聲源的方向,計算每個麥克風接收到聲音的延遲時間。
  2. 信號延遲補償:對每個麥克風的信號進行相應的延遲補償,使來自目標方向的信號在時間上對齊。
  3. 信號叠加:將所有補償後的信號進行叠加,增強來自目標方向的聲音。

2.3 二維波束形成實現

實現二維波束形成需要在水平方向(Azimuth)和垂直方向(Elevation)上對每個目標角度進行計算。以下程式碼展示了如何計算延遲並進行波束形成:


def beamforming(audio_data, mic_positions, angle_h, angle_v, speed_of_sound=343):
    """
    執行二維波束形成
    :param audio_data: (通道數, 樣本數) 的音訊數據
    :param mic_positions: (通道數, 2) 的麥克風位置數組
    :param angle_h: 水平角度 (度)
    :param angle_v: 垂直角度 (度)
    :param speed_of_sound: 聲速 (默認343 m/s)
    :return: 波束形成後的信號
    """
    delays = np.zeros(len(mic_positions))
    for i, pos in enumerate(mic_positions):
        # 計算每個麥克風的延遲時間
        delay = (pos[0] * np.sin(np.radians(angle_h)) + pos[1] * np.sin(np.radians(angle_v))) / speed_of_sound
        delays[i] = delay
    
    # 對音訊數據進行延遲補償
    delayed_data = np.zeros_like(audio_data)
    for i in range(len(mic_positions)):
        sample_shift = int(delays[i] * RATE)
        delayed_data[i] = np.roll(audio_data[i], sample_shift)
    
    # 合併延遲後的音訊數據
    beamformed_signal = np.sum(delayed_data, axis=0)
    return beamformed_signal
    

2.4 信號前處理與噪聲抑制

為了提升波束形成的效果,可以在前處理階段進行噪聲抑制,例如使用濾波器來去除背景噪聲,或者應用自適應波束形成算法來動態調整波束以應對不同的噪聲環境。下方程式碼展示了如何應用高通濾波器去除低頻噪聲:


from scipy.signal import butter, lfilter

def highpass_filter(data, cutoff=1000, fs=RATE, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    # 設計高通濾波器
    b, a = butter(order, normal_cutoff, btype='high', analog=False)
    y = lfilter(b, a, data)
    return y

# 應用高通濾波器
filtered_data = highpass_filter(audio_data)
    

2.5 綜合波束形成流程

以下流程圖展示了二維波束形成的整體流程:

步驟 描述
1 音訊數據採集
2 數據前處理(如濾波、降噪)
3 計算延遲時間
4 延遲補償並叠加信號
5 生成波束形成後的信號

3. 實時Heatmap生成與可視化

3.1 Heatmap的基本概念

Heatmap(熱圖)是一種可視化工具,用於表示多維數據的強度或頻率。在波束形成中,Heatmap可用於展示聲源在不同方向上的強度分佈,幫助直觀理解聲源定位結果。熱圖中,每個像素點代表一個特定的方向,顏色深淺則表示該方向上的信號強度。

3.2 使用Matplotlib生成實時Heatmap

Matplotlib是一個強大的Python圖形庫,適合用來生成和更新Heatmap。以下程式碼展示如何初始化並實時更新Heatmap:


import matplotlib.pyplot as plt

# 初始化Heatmap
fig, ax = plt.subplots()
heatmap = ax.imshow(np.zeros((180, 180)), cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
plt.colorbar(heatmap)
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.title('波束形成熱圖')

# 實時更新Heatmap
while True:
    # 讀取音訊數據
    audio_data = np.frombuffer(stream.read(CHUNK), dtype=np.int16).reshape(-1, CHANNELS).T
    
    # 初始化Heatmap數據
    heatmap_data = np.zeros((180, 180))
    
    # 計算每個角度的訊號強度
    for angle_h in range(-90, 90):
        for angle_v in range(-90, 90):
            beamformed_signal = beamforming(audio_data, mic_positions, angle_h, angle_v)
            heatmap_data[angle_v + 90, angle_h + 90] = np.sum(np.abs(beamformed_signal))
    
    # 更新Heatmap
    heatmap.set_data(heatmap_data)
    plt.pause(0.1)  # 更新間隔為0.1秒
    ax.cla()
    heatmap = ax.imshow(heatmap_data, cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
    plt.colorbar(heatmap)
    plt.xlabel('水平角度 (度)')
    plt.ylabel('垂直角度 (度)')
    plt.title('波束形成熱圖')
    

3.3 提升Heatmap生成效率

由於波束形成計算量龐大,實時生成Heatmap時可能會出現延遲。以下是一些優化建議:

  • 並行運算:利用多執行緒或多處理器對不同角度的計算進行並行化。可以使用Python的

    multiprocessing

    threading

    庫來實現。
  • 算法優化:使用NumPy等高效數值運算庫進行矩陣計算,或考慮使用Cython進行C語言級別的優化,提升運算速度。
  • 減少角度範圍或增加間隔:降低Heatmap的解析度(例如,每隔2度計算一次),以減少計算量,同時仍能保留足夠的定位精度。

3.4 Heatmap美化與增強

為了讓Heatmap更加清晰易讀,可以進行以下美化處理:

  • 使用對數刻度:將信號強度轉換為對數刻度,以更好地展示強度差異。
  • 添加標記與注釋:在Heatmap上標記主要聲源方向,或添加數值標註。
  • 調整色彩映射:根據需求選擇合適的色彩映射方案,例如從冷到熱的漸變,以突出重要區域。

4. 完整的實現示例

4.1 完整程式碼範例

以下是一個結合所有部分的完整Python程式碼示例,展示如何從麥克風陣列的信號採集到實時生成Heatmap:


import numpy as np
import pyaudio
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter
import threading

# 音訊參數設定
CHUNK = 1024
RATE = 44100
CHANNELS = 16

# 麥克風陣列位置設定(單位:米)
mic_positions = np.array([
    [0, 0], [0, 0.042], [0, 0.084], [0, 0.126],
    [0.042, 0], [0.042, 0.042], [0.042, 0.084], [0.042, 0.126],
    [0.084, 0], [0.084, 0.042], [0.084, 0.084], [0.084, 0.126],
    [0.126, 0], [0.126, 0.042], [0.126, 0.084], [0.126, 0.126]
])

# 初始化pyaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

# 高通濾波器
def highpass_filter(data, cutoff=1000, fs=RATE, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = butter(order, normal_cutoff, btype='high', analog=False)
    y = lfilter(b, a, data)
    return y

# 波束形成函數
def beamforming(audio_data, mic_positions, angle_h, angle_v, speed_of_sound=343):
    delays = np.zeros(len(mic_positions))
    for i, pos in enumerate(mic_positions):
        delays[i] = (pos[0] * np.sin(np.radians(angle_h)) + pos[1] * np.sin(np.radians(angle_v))) / speed_of_sound
    delayed_data = np.zeros_like(audio_data)
    for i in range(len(mic_positions)):
        sample_shift = int(delays[i] * RATE)
        delayed_data[i] = np.roll(audio_data[i], sample_shift)
    beamformed_signal = np.sum(delayed_data, axis=0)
    return beamformed_signal

# Heatmap更新函數
def update_heatmap():
    while not stop_event.is_set():
        # 讀取音訊數據
        audio_data = np.frombuffer(stream.read(CHUNK), dtype=np.int16).reshape(-1, CHANNELS).T
        # 應用高通濾波器
        audio_data = highpass_filter(audio_data)
        
        # 初始化Heatmap數據
        heatmap_data = np.zeros((180, 180))
        
        # 計算每個角度的訊號強度
        for angle_h in range(-90, 90):
            for angle_v in range(-90, 90):
                beamformed_signal = beamforming(audio_data, mic_positions, angle_h, angle_v)
                heatmap_data[angle_v + 90, angle_h + 90] = np.sum(np.abs(beamformed_signal))
        
        # 更新Heatmap
        ax.clear()
        im = ax.imshow(heatmap_data, cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
        plt.colorbar(im, ax=ax)
        plt.xlabel('水平角度 (度)')
        plt.ylabel('垂直角度 (度)')
        plt.title('波束形成熱圖')
        plt.pause(0.001)  # 短暫暫停以更新圖形

# 初始化Heatmap
fig, ax = plt.subplots()
heatmap = ax.imshow(np.zeros((180, 180)), cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
plt.colorbar(heatmap, ax=ax)
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.title('波束形成熱圖')

# 啟動Heatmap更新執行緒
stop_event = threading.Event()
heatmap_thread = threading.Thread(target=update_heatmap)
heatmap_thread.start()

try:
    plt.show(block=True)
except KeyboardInterrupt:
    pass
finally:
    stop_event.set()
    heatmap_thread.join()
    stream.stop_stream()
    stream.close()
    p.terminate()
    

4.2 執行步驟說明

  1. 初始化音頻流:使用

    pyaudio

    庫打開音頻流,設置通道數(16)、採樣率(44100 Hz)及緩衝區大小(1024個樣本)。
  2. 麥克風位置設定:定義麥克風陣列的幾何位置,這對後續的延遲計算至關重要。
  3. 波束形成計算:根據當前的水平與垂直角度,計算各麥克風的延遲,並將延遲補償後的信號進行叠加,得到增強後的信號。
  4. Heatmap更新:利用Matplotlib進行Heatmap的實時更新,透過多執行緒技術避免阻塞主執行緒,確保圖形界面的流暢性。
  5. 程序終止與資源釋放:通過捕捉鍵盤中斷(Ctrl+C)來優雅地終止程序,並釋放音頻流資源。

4.3 執行與測試

在執行此程式前,請確保所有麥克風均已正確連接並能夠穩定運行。運行程式後,應能實時看到波束形成的Heatmap呈現聲源方向及強度分佈。在測試過程中,您可以移動聲源的位置,觀察Heatmap的變化,以驗證系統的準確性。

4.4 程式碼優化建議

為了提升實時運行的效率,建議對程式碼進行以下優化:

  • 並行運算:利用Python的

    multiprocessing

    threading

    庫,將波束形成計算和Heatmap更新分配到不同的執行緒或進程。
  • 算法優化:使用NumPy進行向量化運算,減少for迴圈的使用,以提高計算速度。
  • 減少計算範圍:可以考慮將角度範圍調整為[-90, 90)度,並增加角度間隔(例如,每2度計算一次),以減少計算量。

5. 優化與擴展建議

5.1 性能優化

為了提升實時運行的效率,可以考慮以下方法:

  • 多執行緒處理:將音訊數據採集與Heatmap生成分離到不同的執行緒,減少延遲並提高處理效率。
  • 使用快速數值計算庫:利用NumPy的向量化運算功能,替代傳統的for迴圈,提升數據處理速度。
  • 減少計算範圍或增加角度間隔:通過降低Heatmap的解析度,或增大角度間隔(如每2度計算一次),以減少計算量,從而提高實時性能。

5.2 增強算法

可以進一步提升波束形成的準確性和對噪聲的抑制能力:

  • 自適應波束形成:根據環境動態調整波束形狀,以更有效地抑制噪聲。這需要實現更複雜的算法,如最小方差無偏估計(MVDR)。
  • 多頻率處理:結合不同頻率的信號來提升定位準確度,特別是在多聲源環境中。
  • 信號預處理:應用高通或低通濾波器,進行降噪處理,提升信號質量,從而提高波束形成效果。

5.3 擴展功能

除了Heatmap外,還可以考慮以下擴展功能:

  • 音源跟踪:在Heatmap基礎上增加音源的移動軌跡追蹤,實現動態聲源定位。
  • 多聲源辨識:提升算法以同時定位多個聲源,適應複雜的聲環境。
  • 3D熱圖:將Heatmap擴展到三維,以包含更多維度的數據,提供更加直觀的聲源分佈視覺化。

6. 結論

本文詳細介紹了如何使用Python實現4x4麥克風陣列的二維波束形成,並將結果以實時Heatmap呈現。通過步驟化的指導與範例程式碼,您可以有效地設置麥克風陣列、進行信號處理及可視化,進而實現精確的聲源定位。進一步的優化與擴展將使系統在更複雜的環境中表現更佳,滿足不同應用需求。

參考資料


Last updated January 24, 2025
Ask me more