GCCPHAT

在做GCCPHAT的时候,发现有时候加权函数会为0,导致无法计算,所以做了如下改进

注:这个代码并不实用,只是自己用来测试的,并不一定能够很好实现,如果有什么错误请告诉我,另外这种改进只是我的臆测,并不知道其他人是怎么做的,matlab有自己的gccphat函数,但是我不知道它是如何处理这个问题的,如果有懂得大神,希望能够不吝赐教

当分母为0时,加权函数 Φ ( ω ) \Phi(\omega) Φ(ω) 的值将无限大,可能导致计算上的问题。因此,需要对这种情况做特殊处理。

一种常见的做法是将分母中为0的元素替换成一个非常小的数,比如可以令:

Φ ( ω ) = { 1 ∣ X 1 ( ω ) X 2 ( ω ) ∣ , ∣ X 1 ( ω ) X 2 ( ω ) ∣ > ϵ   1 ϵ , ∣ X 1 ( ω ) X 2 ∗ ( ω ) ∣ ≤ ϵ \Phi(\omega) = \begin{cases} \frac{1}{|X_1(\omega) X_2^(\omega)|}, & |X_1(\omega) X_2^(\omega)| > \epsilon \ \frac{1}{\epsilon}, & |X_1(\omega) X_2^*(\omega)| \leq \epsilon \end{cases} Φ(ω)={X1(ω)X2(ω)1,X1(ω)X2(ω)>ϵ ϵ1,X1(ω)X2(ω)ϵ

其中 ϵ \epsilon ϵ 是一个非常小的正数,比如 1 0 − 30 10^{-30} 1030。这样,当 ∣ X 1 ( ω ) X 2 ∗ ( ω ) ∣ ≤ ϵ |X_1(\omega) X_2^*(\omega)| \leq \epsilon X1(ω)X2(ω)ϵ 时, Φ ( ω ) \Phi(\omega) Φ(ω) 的值将取到一个很大的数,但不是无限大,可以避免计算上的问题。在实际应用中, ϵ \epsilon ϵ 的取值需要根据具体情况来确定。

代码如下:

function distance = GCC_PHAT(x1, x2, fs, d)
% GCC-PHAT算法

% 快速傅里叶变换
X1 = fft(x1);
X2 = fft(x2);

% 共轭转置
X2_conj = conj(X2);

% 计算互相关函数
R = X1 .* X2_conj;
r = ifft(R);

% 引入频域加权函数
N = length(x1);
epsilon = 1e-30; % 非常小的数
X1X2 = X1 .* X2_conj;
X1X2_abs = abs(X1X2);
Phi = ones(size(X1X2_abs)) ./ X1X2_abs;
Phi(X1X2_abs <= epsilon) = 1 / epsilon; % 分母接近0时的特殊处理
R_phi = R .* Phi;
r_phi = ifft(R_phi);

% 最大值检测
[~, idx] = max(abs(r_phi));
tau = idx - 1;

% 时延估计
c = 340; % 声速,单位:m/s
tau12 = (tau - N/2 - 1) / fs;
distance = tau12 * c + d;
end

这里对分母中小于等于 ϵ \epsilon ϵ 的元素做了特殊处理,其他元素仍按照 Φ ( ω ) = 1 ∣ X 1 ( ω ) X 2 ∗ ( ω ) ∣ \Phi(\omega) = \frac{1}{|X_1(\omega) X_2^*(\omega)|} Φ(ω)=X1(ω)X2(ω)1 的公式求解。

你可能感兴趣的:(matlab)