奥木染村的pxj 2025-03-24 19:13 采纳率: 0%
浏览 8

基于TDOA与fastcia的声源定位

为什么输出结果只有一个估计声源且误差较大,求解答

%% 多声源三维定位(修正版)
clc; clear; close all;

% 参数设置
c = 340;             % 声速 (m/s)
fs = 44100;          % 采样率
duration = 1;        % 缩短信号时长至1秒以降低计算量
t = 0:1/fs:duration; 
num_mics = 5;        
num_sources = 2;     

%% 1. 生成模拟声源信号
source1 = 0.5 * chirp(t, 100, duration, 1500); 
source2 = 0.5 * (sin(2*pi*300*t) + 0.5*sin(2*pi*600*t));
source_pos = [2, 3, 4; 5, 1, 3]; 
orig_signals = [source1; source2];

%% 2. 定义非共面麦克风阵列
mic_pos = [0,0,0; 3,0,0; 0,4,0; 0,0,5; 3,4,0];
assert(rank(mic_pos)==3, '麦克风共面!');

%% 3. 信号传播模型(精确时延处理)
mixed_signals = zeros(num_mics, length(t));
for mic_idx = 1:num_mics
    for src_idx = 1:num_sources
        dist = norm(source_pos(src_idx,:) - mic_pos(mic_idx,:));
        delay_samples = round(dist/c * fs);
        valid_start = max(1, delay_samples+1);
        valid_len = length(t) - valid_start + 1;
        if valid_len > 0
            mixed_signals(mic_idx, valid_start:end) = mixed_signals(mic_idx, valid_start:end) + ...
                (1/(1+dist)) * orig_signals(src_idx, 1:valid_len);
        end
    end
    mixed_signals(mic_idx,:) = awgn(mixed_signals(mic_idx,:), 20);
end

%% 4. 数据预处理(关键修正)
% 转置数据为 N × M 格式 (采样点数 × 麦克风数)
mixed_signals_centered = mixed_signals' - mean(mixed_signals', 1); % 中心化
[E, D] = eig(cov(mixed_signals_centered));
whitening_matrix = inv(sqrt(D)) * E';
whitened_signals = (whitening_matrix * mixed_signals_centered')'; % 白化后转回 M × N

%% 5. ICA分离(修正输入维度)
fastica_path = 'C:\Program Files\MATLAB\R2024a\toolbox\fastica\FastICA_25';
addpath('fastica');
[icasig, A, W] = fastica(whitened_signals', 'numOfIC', num_sources, 'g', 'tanh');

% 信号排序与符号校正
corr_matrix = corr(icasig', orig_signals(:,1:size(icasig,2))'); 
[~, idx] = max(abs(corr_matrix), [], 2);
icasig = icasig(idx, :);
for i = 1:num_sources
    if corr(icasig(i,:), orig_signals(i,1:size(icasig,2))) < 0
        icasig(i,:) = -icasig(i,:);
    end
end

%% 6. TDOA定位(加权Chan算法)
estimated_positions = zeros(num_sources, 3);
for src = 1:num_sources
    % 计算相对时延(GCC-PHAT)
    tdoa = zeros(1, num_mics-1);
    ref_sig = icasig(src, :);
    for mic = 2:num_mics
        target_sig = mixed_signals(mic, :);
        [corr_val, lags] = xcorr(ref_sig, target_sig, 'coeff');
        [~, max_idx] = max(abs(corr_val));
        tdoa(mic-1) = lags(max_idx)/fs;
    end
    
    % 构建方程组
    A_mat = []; b_vec = [];
    for k = 2:num_mics
        mic_k = mic_pos(k,:);
        mic_ref = mic_pos(1,:);
        A_mat = [A_mat; 2*(mic_k - mic_ref)];
        b_val = sum(mic_k.^2 - mic_ref.^2) - (c*tdoa(k-1))^2;
        b_vec = [b_vec; b_val];
    end
    
    % 加权最小二乘
    weights = 1./var(A_mat, 0, 2);
    W = diag(weights);
    pos_est = (A_mat'*W*A_mat) \ (A_mat'*W*b_vec);
    estimated_positions(src,:) = pos_est';
end

%% 7. 重构各麦克风的源分量信号
separated_signals = zeros(num_mics, num_sources, size(icasig,2));
for src = 1:num_sources
    separated_signals(:, src, :) = A(:, src) * icasig(src, :);
end

%% 8. TDOA定位(改进版Chan算法)
estimated_positions = zeros(num_sources, 3);
for src = 1:num_sources
    % 计算相对时延
    tdoa = zeros(1, num_mics-1);
    ref_sig = squeeze(separated_signals(1, src, :))';
    for mic = 2:num_mics
        target_sig = squeeze(separated_signals(mic, src, :))';
        % 使用广义互相关
        [corr_val, lags] = xcorr(ref_sig, target_sig, 'coeff'); 
        [~, idx] = max(abs(corr_val));
        tdoa(mic-1) = lags(idx)/fs;
    end
    disp(['声源 ', num2str(src), ' 的 TDOA 值:']);
    disp(tdoa);
    
    % 构建线性方程组
    A_mat = [];
    b_vec = [];
    mic_ref = mic_pos(1,:);
    for k = 2:num_mics
        mic_k = mic_pos(k,:);
        a = 2*(mic_k - mic_ref);
        b = sum(mic_k.^2 - mic_ref.^2) - (c*tdoa(k-1))^2;
        A_mat = [A_mat; a];
        b_vec = [b_vec; b];
    end
    disp(['声源 ', num2str(src), ' 的 A_mat 矩阵:']);
    disp(A_mat);
    disp(['声源 ', num2str(src), ' 的 b_vec 向量:']);
    disp(b_vec);
    
    weights = 1 ./ var(A_mat, 0, 2);  % 按行计算方差
    W = diag(weights);                % 创建对角权重矩阵
    
    % 验证矩阵维度
    assert(size(A_mat,1) == size(W,1), '矩阵维度不匹配!A_mat:%dx%d, W:%dx%d',...
           size(A_mat,1), size(A_mat,2), size(W,1), size(W,2));
    
    % 加权最小二乘解
    pos_est = (A_mat'*W*A_mat) \ (A_mat'*W*b_vec);
    estimated_positions(src,:) = pos_est';
end

%% 9. 可视化结果
figure;
% 绘制麦克风阵列
scatter3(mic_pos(:,1), mic_pos(:,2), mic_pos(:,3), ...
        'filled', 'MarkerFaceColor', [0.2 0.4 0.8], 'SizeData', 120);
hold on;

% 标注麦克风
mic_labels = cellstr(num2str((1:num_mics)'));
text(mic_pos(:,1)+0.1, mic_pos(:,2)+0.1, mic_pos(:,3)+0.1, mic_labels, ...
    'FontWeight', 'bold', 'Color', 'k');

% 绘制真实声源
scatter3(source_pos(:,1), source_pos(:,2), source_pos(:,3), ...
        'pentagram', 'filled', 'MarkerFaceColor', 'r', 'SizeData', 200);

% 绘制估计声源
scatter3(estimated_positions(:,1), estimated_positions(:,2), estimated_positions(:,3), ...
        'hexagram', 'LineWidth', 3, 'MarkerEdgeColor', 'g', 'SizeData', 200);

% 设置图形属性
legend('麦克风阵列', '真实声源', '估计声源', 'Location', 'northeast');
title(sprintf('多声源三维定位结果 (平均误差: %.2f cm)', ...
    100*mean(vecnorm(estimated_positions - source_pos, 2, 2))));
xlabel('X轴 (米)'); ylabel('Y轴 (米)'); zlabel('Z轴 (米)');
grid on; axis equal; view(25, 30);
set(gca, 'FontSize', 12);
saveas(gcf, '多声源定位结果.png');

% 绘制分离后的信号与原始信号对比
figure;
for i = 1:num_sources
    subplot(num_sources, 2, 2*i-1);
    plot(orig_signals(i, :));
    title(sprintf('原始信号%d', i));
    subplot(num_sources, 2, 2*i);
    plot(icasig(i, :));
    title(sprintf('分离信号%d', i));
end

%% 10. 输出误差分析
fprintf('===== 定位误差分析 =====\n');
for src_idx = 1:num_sources
    error = norm(estimated_positions(src_idx, :) - source_pos(src_idx, :));
    fprintf('声源%d定位误差: %.4f 米\n', src_idx, error);
end    

img

  • 写回答

3条回答 默认 最新

  • 道友老李 JWE233286一种基于机器视觉的水表指针读数识别及修正的方法 专利发明者 2025-03-24 19:13
    关注
    让【道友老李】来帮你解答,本回答参考gpt编写,并整理提供,如果还有疑问可以点击头像关注私信或评论。
    如果答案让您满意,请采纳、关注,非常感谢!
    根据提供的代码,输出结果只有一个估计声源且误差较大的原因可能是因为在TDOA定位中的代码实现中存在一些问题。以下是可能导致此问题的几个原因和建议的解决方案:
    1. 非共面麦克风阵列:在代码中对麦克风的位置进行了定义和断言,确保麦克风不共面。如果麦克风的位置设置存在误差或者麦克风共面,可能导致定位错误。建议确保麦克风的位置设置准确,且不共面。
    2. 信号传播模型中的非共面麦克风阵列:在信号传播模型部分,根据麦克风和声源之间的距离计算时延。如果非共面麦克风阵列设置不正确,可能导致计算出现误差。建议检查非共面麦克风阵列的设置是否准确。
    3. TDOA定位中的算法实现:在TDOA定位部分,使用了加权Chan算法来计算估计的声源位置。可能在计算相对时延或构建方程组的过程中存在错误,导致最终估计位置不准确。建议仔细审查TDOA定位的实现,并确保算法的正确性。
    4. 数据预处理中的白化和ICA分离:在数据预处理和ICA分离部分也可能存在问题,导致最终估计的声源位置不准确。建议检查数据预处理和ICA分离的实现,确保对信号的处理正确。 综上所述,建议逐步检查代码中各个部分的实现,确保每个步骤的正确性,从而获得准确的多声源三维定位结果。如果需要进一步帮助或代码实现可以提供更详细的信息。
    评论

报告相同问题?

问题事件

  • 创建了问题 3月24日