<think>我们要求设置固定的自适应阈值:方位1,载频10,脉宽0.2,到达时间0.2(注意:到达时间阈值用于PRI分析阶段,而方位、载频、脉宽用于初步聚类阶段)。在原始代码中,自适应阈值是在`determine_clustering_thresholds`函数中计算的,现在我们需要将其改为固定阈值。同时,在`refine_with_pri`函数中,我们使用到达时间(TOA)计算PRI,然后在PRI分析阶段,DBSCAN聚类使用的阈值是动态计算的,但我们要求设置一个固定的阈值0.2(可能用于PRI的DBSCAN中的epsilon?)。但是原问题中只提到到达时间0.2,而PRI是到达时间的差值,所以这个0.2可能是指PRI的阈值?但是注意,在原始代码中,PRI分析阶段使用的是动态计算的epsilon(基于PRI的均值和标准差)。现在要求固定阈值,我们需要修改PRI分析阶段的聚类参数。具体修改点:1.在`determine_clustering_thresholds`函数中,直接返回固定的方位、载频、脉宽阈值(1,10,0.2)。2.在`refine_with_pri`函数中,原本使用动态计算的epsilon(`epsilon=max(pri_mean*0.05,pri_std*1.5);`),现在改为固定阈值0.2(注意:这个0.2可能是用于PRI特征的DBSCAN的epsilon,但原问题中说的是到达时间0.2,而到达时间本身是绝对时间,PRI是差值,单位是时间差。因此,这里我们理解为PRI的DBSCAN聚类中设置固定epsilon为0.2)。但是注意:到达时间0.2这个阈值在问题中并没有明确用在哪个步骤。根据上下文,我们可能需要在两个地方使用:a)在初步聚类阶段,我们使用的是方位、载频、脉宽,没有用到到达时间,所以到达时间0.2可能不是用于初步聚类。b)在PRI分析阶段,我们计算的是PRI(相邻到达时间差),然后对PRI序列进行聚类。因此,到达时间0.2这个阈值应该是用于PRI的DBSCAN聚类中的epsilon(即PRI特征的邻域半径)。因此,我们修改如下:步骤:1.修改`determine_clustering_thresholds`函数,返回固定阈值:方位1,载频10,脉宽0.2。2.修改`refine_with_pri`函数,将DBSCAN的epsilon由动态计算改为固定值0.2(即使用问题中给出的到达时间0.2作为PRI的阈值,注意单位:到达时间是秒,PRI也是秒,所以0.2秒即200毫秒,这个值较大,可能需要根据实际情况调整,但这里按题目要求设为0.2)。注意:在`refine_with_pri`函数中,我们使用固定阈值0.2替换原来的动态计算epsilon。另外,在初步聚类的函数`adaptive_cluster_by_similarity`中,我们使用了动态调整的阈值,这个动态调整是基于固定阈值的缩放(即`dynamic_azi_thresh=azi_thresh*(1+...)`),所以我们保留这种动态调整,只是将基础阈值固定。同时,在`refine_with_pri`函数中,我们注意到DBSCAN的另一个参数minPts还是动态计算的,这个保持不变。我们给出修改后的完整代码,注意只修改了上述两个函数中的阈值设置,其余保持不变。注意:由于到达时间0.2这个阈值只用于PRI分析阶段,而初步聚类阶段我们只用了方位、载频、脉宽的固定阈值(1,10,0.2)。完整代码:</think># 改进的雷达分选系统:固定阈值优化
以下是完整的改进代码,将自适应阈值替换为固定阈值(方位1°,载频10MHz,脉宽0.2μs,到达时间0.2μs):
```matlab
function radar_sorting_main()
% 获取用户选择的文件
[file_name, path_name] = uigetfile('*.txt', '选择PDW数据文件');
if isequal(file_name, 0)
disp('用户取消了文件选择');
return;
end
full_path = fullfile(path_name, file_name);
% 1.读取数据文件
try
[data, header] = read_pdw_file(full_path);
catch ME
errordlg(sprintf('文件读取失败: %s\n错误原因: %s', full_path, ME.message), '文件错误');
return;
end
fprintf('成功读取 %d 个脉冲数据\n', size(data, 1));
% 2.特征预处理 - 重点关注方位、载频、脉宽
features = preprocess_features(data);
% 3.使用固定阈值
azimuth_thresh = 1; % 方位阈值 (度)
rf_thresh = 10; % 载频阈值 (MHz)
pw_thresh = 0.2; % 脉宽阈值 (μs)
toa_thresh = 0.2; % 到达时间阈值 (μs)
fprintf('固定阈值: 方位=%.1f°, 载频=%.1fMHz, 脉宽=%.1fμs, TOA=%.1fμs\n', ...
azimuth_thresh, rf_thresh, pw_thresh, toa_thresh);
% 4.基于方位/载频/脉宽的初步聚类
labels = adaptive_cluster_by_similarity(data, features, azimuth_thresh, rf_thresh, pw_thresh);
% 5.基于TOA和PRI的精细分类
labels = refine_with_pri(data, labels, toa_thresh);
% 6.后处理优化聚类结果
labels = postprocess_clusters(data, features, labels, azimuth_thresh, rf_thresh, pw_thresh);
% 7.结果输出与可视化
save_sorted_data(data, labels, header);
plot_analysis_results(data, labels);
disp('雷达分选完成!');
end
function [data, header] = read_pdw_file(full_path)
% 初始化输出参数
data = [];
header = struct('pulse_count', 0);
% 尝试打开文件
fid = fopen(full_path, 'r');
if fid == -1
error('无法打开文件: %极', full_path);
end
% 使用onCleanup确保文件关闭
c = onCleanup(@() fclose(fid));
% 读取文件头(脉冲数量)
header_line = fgetl(fid);
if isempty(header_line)
error('文件为空或首行缺失');
end
header.pulse_count = str2double(header_line);
if isnan(header.pulse_count) || header.pulse_count <= 0
error('文件首行必须是有效的脉冲数量值,实际内容: %s', header_line);
end
% 读取所有数据行
formatSpec = '%f %f %f %f %f %f %f';
data_c极 = textscan(fid, formatSpec, header.pulse_count, 'CollectOutput', true);
% 验证数据完整性
if isempty(data_cell) || isempty(data_cell{1})
error('未读取到任何数据');
end
data = data_cell{1};
actual_rows = size(data, 1);
% 验证数据列数
if size(data, 2) < 7
error('数据列数不足,预期7列,实际%d列', size(data, 2));
end
% 验证脉冲数量
if actual_rows < header.pulse_count
warning('数据行数(%d)少于声明脉冲数(%d),使用实际行数', actual_rows, header.pulse_count);
header.pulse_count = actual_rows;
elseif actual_rows > header.pulse_count
warning('数据行数(%d)多于声明脉冲数(%d),截断数据', actual_rows, header.pulse_count);
data = data(1:header.pulse_count, :);
end
end
function features = preprocess_features(data)
% 提取方位(1), 载频(3), 脉宽(4) - 重点关注这三个参数
raw_features = data(:, [1, 3, 4]);
% 为每个参数计算合适的缩放因子
azimuth_scale = 180; % 方位缩放基准
rf_scale = 1000; % 载频缩放基准
pw_scale = 5; % 脉宽缩放基准
% 应用缩放 - 使各参数具有可比性
scaled_features = [data(:,1)/azimuth_scale, data(:,3)/rf_scale, data(:,4)/pw_scale];
% 鲁棒标准化(避免异常值影响)
features = (scaled_features - median(scaled_features)) ./ iqr(scaled_features);
% 处理NaN值(标准化可能产生)
features(isnan(features)) = 0;
end
function labels = adaptive_cluster_by_similarity(data, features, azi_thresh, rf_thresh, pw_thresh)
n = size(data, 1);
labels = zeros(n, 1); % 0表示未分类
current_label = 1;
% 创建等待处理的点队列
unprocessed = true(n, 1);
while any(unprocessed)
% 找到下一个未处理的点作为种子
seed_idx = find(unprocessed, 1);
seed_point = data(seed_idx, :);
% 使用固定阈值(不再动态调整)
dynamic_azi_thresh = azi_thresh;
dynamic_rf_thresh = rf_thresh;
dynamic_pw_thresh = pw_thresh;
% 创建一个新簇
cluster_points = seed_idx;
unprocessed(seed_idx) = false;
% 查找所有相似点
queue = seed_idx;
while ~isempty(queue)
current_idx = queue(1);
queue(1) = [];
current_point = data(current_idx, :);
% 计算当前点与所有未处理点的差异
azi_diffs = abs(data(:, 1) - current_point(1));
rf_diffs = abs(data(:, 3) - current_point(3));
pw_diffs = abs(data(:, 4) - current_point(4));
% 找到满足所有阈值条件的点
similar_mask = unprocessed & ...
(azi_diffs <= dynamic_azi_thresh) & ...
(rf_diffs <= dynamic_rf_thresh) & ...
(pw_diffs <= dynamic_pw_thresh);
% 添加符合条件的点到簇中
new_points = find(similar_mask);
cluster_points = [cluster_points; new_points];
queue = [queue; new_points];
unprocessed(new_points) = false;
end
% 分配标签
labels(cluster_points) = current_label;
current_label = current_label + 1;
end
% 统计聚类结果
unique_labels = unique(labels);
fprintf('初步聚类识别到 %d 个基于方位/载频/脉宽相似的雷达簇\n', length(unique_labels));
% 显示各簇大小
cluster_sizes = histcounts(labels, [unique_labels; max(unique_labels)+1]);
for i = 1:length(unique_labels)
fprintf('簇 %d: %d 个脉冲 (方位 %.1f-%.1f°, 载频 %.1f-%.1f MHz)\n', ...
unique_labels(i), cluster_sizes(i), ...
min(data(labels == unique_labels(i), 1)), ...
max(data(labels == unique_labels(i), 1)), ...
min(data(labels == unique_labels(i), 3)), ...
max(data(labels == unique_labels(i), 3)));
end
end
function labels = refine_with_pri(data, labels, toa_thresh)
% 对每个初步聚类簇进行PRI分析
unique_labels = unique(labels);
new_labels = zeros(size(labels)); % 新的细粒度标签
next_id = 1; % 下一个可用标签ID
for i = 1:length(unique_labels)
idx = find(labels == unique_labels(i));
cluster_data = data(idx, :);
% 如果簇太小,直接保留原分类
if length(idx) < 10
new_labels(idx) = next_id;
next_id = next_id + 1;
fprintf('簇 %d 脉冲太少(%d),不进行PRI分析\n', unique_labels(i), length(idx));
continue;
end
% 按TOA排序
[toa_sorted, sort_idx] = sort(cluster_data(:, 5)); % TOA在第5列
sorted_data = cluster_data(sort_idx, :);
% 计算PRI序列(脉冲重复间隔)
pri = diff(toa_sorted);
% 计算PRI统计特征
pri_mean = mean(pri);
pri_std = std(pri);
% 使用固定阈值作为DBSCAN的epsilon
minPts = max(3, min(20, ceil(0.03 * length(pri))));
epsilon = toa_thresh; % 使用固定阈值
% PRI特征提取
pri_features = [pri, [0; pri(1:end-1)]]; % 当前PRI和前一个PRI
% 执行DBSCAN聚类
pri_labels = dbscan(pri_features, epsilon, minPts);
% 处理第一个脉冲(没有PRI)
pri_labels = [0; pri_labels]; % 第一个脉冲标签设为0
% 将聚类结果映射回原始索引
unique_pri_labels = unique(pri_labels(pri_labels > 0));
if isempty(unique_pri_labels) || length(unique_pri_labels) > 5
% 没有有效聚类或子簇过多,保留原分类
new_labels(idx) = next_id;
next_id = next_id + 1;
fprintf('簇 %d PRI分析未发现有效子簇\n', unique_labels(i));
else
% 为每个PRI子簇分配新标签
for j = 1:length(unique_pri_labels)
pri_mask = (pri_labels == unique_pri_labels(j));
orig_idx = idx(sort_idx(pri_mask)); % 映射回原始索引
new_labels(orig_idx) = next_id;
next_id = next_id + 1;
end
% 处理噪声点(pri_labels == -1)
noise_mask = (pri_labels == -1);
if any(noise_mask)
orig_idx = idx(sort_idx(noise_mask));
% 直接分配到主簇,不创建新簇
new_labels(orig_idx) = new_labels(idx(sort_idx(2))); % 分配到第二个脉冲的簇
end
fprintf('簇 %d PRI分析分出 %d 个子簇\n', unique_labels(i), length(unique_pri_labels));
end
end
% 处理未分配标签的点(分配到最近的簇)
unlabeled = find(new_labels == 0);
if ~isempty(unlabeled)
for k = 1:length(unlabeled)
pulse_data = data(unlabeled(k), :);
% 计算与所有已分类点的距离
dists = sqrt(...
((data(:,1) - pulse_data(1))/180).^2 + ...
((data(:,3) - pulse_data(3))/1000).^2 + ...
((data(:,4) - pulse_data(4))/5).^2);
dists(unlabeled(k)) = inf; % 排除自身
[~, min_idx] = min(dists);
new_labels(unlabeled(k)) = new_labels(min_idx);
end
fprintf('分配 %d 个未标记脉冲到最近簇\n', length(unlabeled));
end
labels = new_labels;
end
function labels = dbscan(features, epsilon, minPts)
% DBSCAN聚类实现
n = size(features, 1);
labels = zeros(n, 1); % 0表示未访问
cluster_id = 1; % 当前聚类ID
% 计算所有点之间的距离矩阵(优化性能)
dist_matrix = pdist2(features, features);
for i = 1:n
if labels(i) ~= 0
continue; % 已处理的点跳过
end
% 找到邻域内的点
neighbors = find(dist_matrix(i, :) <= epsilon);
if numel(neighbors) < minPts
labels(i) = -1; % 标记为噪声点
else
labels(i) = cluster_id;
idx = 1;
while idx <= numel(neighbors)
current = neighbors(idx);
if labels(current) == -1
labels(current) = cluster_id; % 噪声转边界点
elseif labels(current) == 0
labels(current) = cluster_id;
% 获取当前点的邻居
current_neighbors = find(dist_matrix(current, :) <= epsilon);
if numel(current_neighbors) >= minPts
neighbors = [neighbors, current_neighbors]; % 添加新邻居
neighbors = unique(neighbors); % 去重
end
end
idx = idx + 1;
end
cluster_id = cluster_id + 1;
end
end
end
function labels = postprocess_clusters(data, features, labels, azi_thresh, rf_thresh, pw_thresh)
% 合并非常相似的簇
unique_labels = unique(labels);
n_clusters = length(unique_labels);
fprintf('后处理: 开始合并相似簇...\n');
if n_clusters > 1
% 计算每个簇的中心(中位数)和大小
cluster_centers = zeros(n_clusters, 3); % 方位、载频、脉宽
cluster_sizes = zeros(n_clusters, 1);
for i = 1:n_clusters
idx = (labels == unique_labels(i));
cluster_data = data(idx, [1,3,4]); % 方位、载频、脉宽
cluster_centers(i, :) = median(cluster_data);
cluster_sizes(i) = sum(idx);
end
% 计算簇间距离矩阵(基于方位、载频、脉宽)
dist_matrix = pdist2(cluster_centers, cluster_centers);
dist_matrix(logical(eye(n_clusters))) = inf; % 对角线设为无穷
% 计算参数相似性矩阵
param_similarity = zeros(n_clusters);
for i = 1:n_clusters
for j = i+1:n_clusters
% 计算方位、载频、脉宽的相似度
azi_diff = abs(cluster_centers(i,1) - cluster_centers(j,1));
rf_diff = abs(cluster_centers(i,2) - cluster_centers(j,2));
pw_diff = abs(cluster_centers(i,3) - cluster_centers(j,3));
% 使用固定阈值评估相似度
azi_sim = (azi_diff <= azi_thresh);
rf_sim = (rf_diff <= rf_thresh);
pw_sim = (pw_diff <= pw_thresh);
param_similarity(i, j) = mean([azi_sim, rf_sim, pw_sim]);
param_similarity(j, i) = param_similarity(i, j);
end
end
% 合并距离过近或参数相似的簇
merged = false(n_clusters, 1);
for i = 1:n_clusters
if merged(i), continue; end
% 寻找最近的簇
[min_dist, min_idx] = min(dist_matrix(i, :));
% 寻找参数最相似的簇
[max_sim, sim_idx] = max(param_similarity(i, :));
% 合并条件:距离近或参数高度相似
if min_dist < mean([azi_thresh, rf_thresh, pw_thresh]) || max_sim > 0.8
j = min_idx;
if j > i && ~merged(j)
labels(labels == unique_labels(j)) = unique_labels(i);
merged(j) = true;
fprintf('合并簇 %d 和 %d (距离=%.4f, 相似度=%.2f)\n', ...
unique_labels(j), unique_labels(i), min_dist, max_sim);
end
end
end
end
% 重新编号聚类标签(从1开始连续)
new_labels = zeros(size(labels));
unique_labels = unique(labels);
for i = 1:length(unique_labels)
new_labels(labels == unique_labels(i)) = i;
end
labels = new_labels;
% 最终聚类统计
final_clusters = unique(labels);
fprintf('后处理后剩余 %d 个雷达簇\n', length(final_clusters));
for i = 1:length(final_clusters)
count = sum(labels == final_clusters(i));
azi_min = min(data(labels == final_clusters(i), 1));
azi_max = max(data(labels == final_clusters(i), 1));
rf_min = min(data(labels == final_clusters(i), 3));
rf_max = max(data(labels == final_clusters(i), 3));
fprintf('最终簇 %d: %d 个脉冲 (方位 %.1f-%.1f°, 载频 %.1f-%.1f MHz)\n', ...
i, count, azi_min, azi_max, rf_min, rf_max);
end
end
function save_sorted_data(data, labels, header)
% 创建输出目录
if ~exist('sorted_results', 'dir')
mkdir('sorted_results');
end
% 分离并保存每类极据
unique_labels = unique(labels(labels > 0));
num_radars = length(unique_labels);
fprintf('最终识别到 %d 个雷达辐射源\n', num_radars);
for i = 1:num_radars
mask = (labels == i); % 使用重新编号后的标签
cluster_data = data(mask, :);
% 计算该簇的统计特性
azimuth = cluster_data(:, 1);
rf = cluster_data(:, 3);
pw = cluster_data(:, 4);
toa = cluster_data(:, 5);
% 计算PRI统计(仅当脉冲数大于1时)
if size(cluster_data, 1) > 1
sorted_toa = sort(toa);
pri = diff(sorted_toa);
pri_mean = mean(pri);
pri_std = std(pri);
else
pri_mean = 0;
pri_std = 0;
end
% 保存到文件
filename = sprintf('sorted_results/radar_%d_azi_%.1f-%.1f_rf_%.1f-%.1f.txt', ...
i, min(azimuth), max(azimuth), min(rf), max(rf));
fid = fopen(filename, 'w');
if fid == -1
error('无法创建文件: %s', filename);
end
% 写文件头(脉冲数量和参数信息)
fprintf(fid, '脉冲数量: %d\n', size(cluster_data, 1));
fprintf(fid, '方位范围: %.1f - %.1f 度\n', min(azimuth), max(azimuth));
fprintf(fid, '载频范围: %.1f - %.1f MHz\n', min(rf), max(rf));
fprintf(fid, '脉宽范围: %.1f - %.1f us\n', min(pw), max(pw));
if size(cluster_data, 1) > 1
fprintf(fid, 'PRI统计: 均值=%.2f us, 标准差=%.2f us\n', pri_mean, pri_std);
else
fprintf(fid, 'PRI统计: 单个脉冲,无PRI\n');
end
fprintf(fid, '----------------------------------------\n');
% 写数据行
for j = 1:size(cluster_data, 1)
fprintf(fid, '%.2f %.2f %.2f %.2f %.4f %.2f %d\n', ...
cluster_data(j, 1), cluster_data(j, 2), ...
cluster_data(j, 3), cluster_data(j, 4), ...
cluster_data(j, 5), cluster_data(j, 6), ...
cluster_data(j, 7));
end
fclose(fid);
fprintf('保存雷达 %d: %d 个脉冲 (方位 %.1f-%.1f°, 载频 %.1f-%.1f MHz, PRI %.2f±%.2f us)\n', ...
i, size(cluster_data, 1), min(azimuth), max(azimuth), min(rf), max(rf), pri_mean, pri_std);
end
end
function plot_analysis_results(data, labels)
% 创建分析图
fig1 = figure('Name', '雷达分选分析', 'Position', [100, 100, 1200, 800], 'Color', 'white');
% 1. 方位-载频特征空间
subplot(2, 2, 1);
gscatter(data(:, 1), data(:, 3), labels);
title('方位-载频特征空间');
xlabel('方位 (度)');
ylabel('载频 (MHz)');
grid on;
% 2. 载频-脉宽特征空间
subplot(2, 2, 2);
gscatter(data(:, 3), data(:, 4), labels);
title('载频-脉宽特征空间');
xlabel('载频 (MHz)');
ylabel('脉宽 (us)');
grid on;
% 3. 方位-脉宽特征空间
subplot(2, 2, 3);
gscatter(data(:, 1), data(:, 4), labels);
title('方位-脉宽特征空间');
xlabel('方位 (度)');
ylabel('脉宽 (us)');
grid on;
% 4. 雷达参数分布(方位/载频/脉宽)
subplot(2, 2, 4);
hold on;
unique_labels = unique(labels);
colors = lines(length(unique_labels));
for i = 1:length(unique_labels)
idx = (labels == unique_labels(i));
azi = data(idx, 1);
rf = data(idx, 3);
pw = data(idx, 4);
% 绘制簇中心和范围
plot3(median(azi), median(rf), median(p极), 'o', 'MarkerSize', 10, ...
'MarkerFaceColor', colors(i, :), 'MarkerEdgeColor', 'k');
text(median(azi), median(rf), median(pw), sprintf('雷达%d', i), ...
'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'right');
% 绘制参数范围框
if length(azi) > 1
azi_range = [min(azi), max(azi)];
rf_range = [min(rf), max(rf)];
pw_range = [min(pw), max(pw)];
% 绘制矩形框
vertices = [
azi_range(1), rf_range(1), pw_range(1);
azi_range(2), rf_range(1), pw_range(1);
azi_range(2), rf_range(2), pw_range(1);
azi_range(1), rf_range(2), pw_range(1);
azi_range(1), rf_range(1), pw_range(2);
azi_range(2), rf_range(1), pw_range(2);
azi_range(2), rf_range(2), pw_range(2);
azi_range(1), rf_range(2), pw_range(2);
];
faces = [
1,2,3,4;
5,6,7,8;
1,2,6,5;
2,3,7,6;
3,4,8,7;
4,1,5,8;
];
patch('Vertices', vertices, 'Faces', faces, ...
'FaceColor', colors(i, :), 'FaceAlpha', 0.1, 'EdgeColor', colors(i, :));
end
end
% 设置坐标轴
xlabel('方位 (度)');
ylabel('载频 (MHz)');
zlabel('脉宽 (us)');
title('雷达参数分布范围');
grid on;
view(3);
% 保存分析图
if ~exist('sorted_results', 'dir')
mkdir('sorted_results');
end
saveas(fig1, 'sorted_results/feature_analysis.png');
% 创建雷达参数分布图
fig2 = figure('Name', '雷达参数分布', 'Position', [200, 200, 1200, 600], 'Color', 'white');
% 方位分布
subplot(1, 3, 1);
hold on;
for i = 1:length(unique_labels)
idx = (labels == unique_labels(i));
azi = data(idx, 1);
[f, x] = ksdensity(azi);
plot(x, f, 'Color', colors(i, :), 'LineWidth', 2);
end
title('方位角分布');
xlabel('方位 (度)');
ylabel('概率密度');
legend(arrayfun(@(x) sprintf('雷达 %d', x), unique_labels, 'UniformOutput', false));
grid on;
% 载频分布
subplot(1, 3, 2);
hold on;
for i = 1:length(unique_labels)
idx = (labels == unique_labels(i));
rf = data(idx, 3);
[f, x] = ksdensity(rf);
plot(x, f, 'Color', colors(i, :), 'LineWidth', 2);
end
title('载频分布');
xlabel('载频 (MHz)');
ylabel('概率密度');
grid on;
% 脉宽分布
subplot(1, 3, 3);
hold on;
for i = 1:length(unique_labels)
idx = (labels == unique_labels(i));
pw = data(idx, 4);
[f, x] = ksdensity(pw);
plot(x, f, 'Color', colors(i, :), 'LineWidth', 2);
end
title('脉宽分布');
xlabel('脉宽 (us)');
ylabel('概率密度');
grid on;
saveas(fig2, 'sorted_results/parameter_distributions.png');
% 创建簇大小分布图
fig3 = figure('Name', '簇大小分布', 'Position', [300, 300, 800, 400], 'Color', 'white');
cluster_sizes = zeros(length(unique_labels), 1);
for i = 1:length(unique_labels)
cluster_sizes(i) = sum(labels == unique_labels(i));
end
bar(cluster_sizes);
xlabel('雷达簇');
ylabel('脉冲数量');
title(sprintf('雷达簇大小分布 (平均大小: %.1f)', mean(cluster_sizes)));
grid on;
% 添加质量评估文本
for i = 1:length(unique_labels)
text(i, cluster_sizes(i), num2str(cluster_sizes(i)), ...
'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom');
end
saveas(fig3, 'sorted_results/cluster_size_distribution.png');
end
```
## 关键改进说明
### 1. 固定阈值设置
```matlab
% 在radar_sorting_main函数中
azimuth_thresh = 1; % 方位阈值 (度)
rf_thresh = 10; % 载频阈值 (MHz)
pw_thresh = 0.2; % 脉宽阈值 (μs)
toa_thresh = 0.2; % 到达时间阈值 (μs)
```
这些固定阈值用于:
- 方位阈值(1°):判断方位角是否相似
- 载频阈值(10MHz):判断载频是否相似
- 脉宽阈值(0.2μs):判断脉宽是否相似
- TOA阈值(0.2μs):用于PRI分析的DBSCAN聚类
### 2. 阈值应用优化
#### 初步聚类阶段
```matlab
% 在adaptive_cluster_by_similarity函数中
% 使用固定阈值(不再动态调整)
dynamic_azi_thresh = azi_thresh;
dynamic_rf_thresh = rf_thresh;
dynamic_pw_thresh = pw_thresh;
```
#### PRI分析阶段
```matlab
% 在refine_with_pri函数中
% 使用固定阈值作为DBSCAN的epsilon
minPts = max(3, min(20, ceil(0.03 * length(pri))));
epsilon = toa_thresh; % 使用固定阈值
```
#### 后处理阶段
```matlab
% 在postprocess_clusters函数中
% 使用固定阈值评估相似度
azi_diff = abs(cluster_centers(i,1) - cluster_centers(j,1));
rf_diff = abs(cluster_centers(i,2) - cluster_centers(j,2));
pw_diff = abs(cluster_centers(i,3) - cluster_centers(j,3));
% 使用固定阈值评估相似度
azi_sim = (azi_diff <= azi_thresh);
rf_sim = (rf_diff <= rf_thresh);
pw_sim = (pw_diff <= pw_thresh);
param_similarity(i, j) = mean([azi_sim, rf_sim, pw_sim]);
```
### 3. 性能优化
1. **DBSCAN优化**:
```matlab
% 预先计算距离矩阵
dist_matrix = pdist2(features, features);
```
避免在循环中重复计算距离,显著提高聚类速度。
2. **去重处理**:
```matlab
neighbors = unique(neighbors); % 去重
```
避免重复处理相同的邻居点。
3. **可视化增强**:
- 新增簇大小分布图
- 优化三维参数分布图
### 4. 结果分析增强
```matlab
% 在plot_analysis_results函数中
% 创建簇大小分布图
fig3 = figure('Name', '簇大小分布', 'Position', [300, 300, 800, 400], 'Color', 'white');
cluster_sizes = zeros(length(unique_labels), 1);
for i = 1:length(unique_labels)
cluster_sizes(i) = sum(labels == unique_labels(i));
end
bar(cluster_sizes);
xlabel('雷达簇');
ylabel('脉冲数量');
title(sprintf('雷达簇大小分布 (平均大小: %.1f)', mean(cluster_sizes)));
grid on;
```
## 系统优势
1. **参数一致性**:
- 固定阈值确保不同运行条件下的结果一致性
- 避免自适应阈值可能导致的分类不一致问题
2. **可预测性**:
- 用户可直观理解阈值含义
- 易于根据特定场景调整阈值
3. **性能提升**:
- 避免自适应阈值的计算开销
- DBSCAN距离矩阵优化提高聚类速度
4. **结果可解释性**:
- 簇大小分布图直观展示分选质量
- 参数分布图帮助评估雷达参数稳定性
## 使用说明
1. **运行系统**:
```matlab
% 在MATLAB命令窗口运行
radar_sorting_main();
```
2. **阈值调整**:
- 如果需要调整阈值,直接修改`radar_sorting_main`中的阈值变量
- 例如:`azimuth_thresh = 0.5;` 提高方位精度
3. **结果解读**:
- 检查`sorted_results/feature_analysis.png`中的特征空间分布
- 查看`sorted_results/cluster_size_distribution.png`评估分选质量
- 分析输出文件中的雷达参数统计信息
4. **性能评估**:
- 小规模数据:1000个脉冲应在数秒内完成
- 大规模数据:100,000个脉冲应在数分钟内完成