一个改进的MATLAB CVA(Change Vector Analysis)变化检测程序,增加了更多功能和灵活性:
matlab
function change_detection_cva()
% CVA变化检测主函数
% 支持单波段/多波段遥感影像变化检测
%% 参数设置
params = struct();
params.useAutoThreshold = true; % 使用自动阈值(Otsu)
params.manualThreshold = 0.25; % 手动阈值(当useAutoThreshold=false时使用)
params.morphologyEnabled = true; % 启用形态学后处理
params.structElementRadius = 3; % 形态学结构元素半径
params.saveResults = true; % 保存结果
params.showPlots = true; % 显示结果图像
params.bandSelection = []; % 波段选择([]表示所有波段)
%% 读取影像
[img1, img2] = load_images();
%% 预处理
[img1, img2] = preprocess_images(img1, img2, params.bandSelection);
%% CVA核心计算
[magnitude, diff_img] = compute_cva(img1, img2);
%% 阈值分割
binary_change = threshold_segmentation(magnitude, params);
%% 后处理
if params.morphologyEnabled
cleaned_change = morphological_processing(binary_change, params.structElementRadius);
else
cleaned_change = binary_change;
end
%% 结果显示与保存
display_results(img1, img2, magnitude, cleaned_change, params);
%% 可选:导出变化统计信息
export_statistics(cleaned_change);
end
%% 辅助函数
function [img1, img2] = load_images()
% 交互式选择影像文件
[filename1, pathname1] = uigetfile({'*.tif;*.jpg;*.png;*.img','影像文件 (*.tif, *.jpg, *.png, *.img)'},...
'选择时期1影像');
[filename2, pathname2] = uigetfile({'*.tif;*.jpg;*.png;*.img','影像文件 (*.tif, *.jpg, *.png, *.img)'},...
'选择时期2影像');
if isequal(filename1,0) || isequal(filename2,0)
error('未选择影像文件');
end
img1 = imread(fullfile(pathname1, filename1));
img2 = imread(fullfile(pathname2, filename2));
% 检查尺寸一致性
if ~isequal(size(img1), size(img2))
error('错误:两幅影像尺寸不一致 (%s: %dx%d, %s: %dx%d)',...
filename1, size(img1,1), size(img1,2),...
filename2, size(img2,1), size(img2,2));
end
end
function [img1, img2] = preprocess_images(img1, img2, bandSelection)
% 转换为双精度浮点型
img1 = im2double(img1);
img2 = im2double(img2);
% 波段选择
if ~isempty(bandSelection)
if ndims(img1) == 3
img1 = img1(:,:,bandSelection);
img2 = img2(:,:,bandSelection);
else
warning('波段选择仅适用于多波段影像');
end
end
% 直方图匹配(可选)
% img2 = histeq(img2, img1);
end
function [magnitude, diff_img] = compute_cva(img1, img2)
% 计算变化向量和幅度
if ndims(img1) == 3
% 多波段影像
diff_img = zeros(size(img1));
for b = 1:size(img1, 3)
diff_img(:,:,b) = img2(:,:,b) - img1(:,:,b);
end
magnitude = sqrt(sum(diff_img.^2, 3));
else
% 单波段影像
diff_img = img2 - img1;
magnitude = abs(diff_img);
end
% 归一化幅度到0-1范围
magnitude = (magnitude - min(magnitude(:))) / (max(magnitude(:)) - min(magnitude(:)));
end
function binary_change = threshold_segmentation(magnitude, params)
% 变化区域分割
if params.useAutoThreshold
% Otsu自动阈值
level = graythresh(magnitude);
binary_change = imbinarize(magnitude, level);
else
% 手动阈值
binary_change = magnitude > params.manualThreshold;
end
end
function processed = morphological_processing(binary_img, radius)
% 形态学后处理
se = strel('disk', radius);
processed = imopen(binary_img, se); % 开运算去除小物体
processed = imclose(processed, se); % 闭运算填充小孔
processed = bwareaopen(processed, 50); % 移除小面积区域
end
function display_results(img1, img2, magnitude, change_map, params)
% 显示结果
if params.showPlots
figure('Name', 'CVA变化检测结果', 'NumberTitle', 'off');
% 原始影像
subplot(2,2,1), imshow(img1), title('时期1影像');
subplot(2,2,2), imshow(img2), title('时期2影像');
% 变化幅度
subplot(2,2,3), imshow(magnitude, []), title('变化向量幅度');
colorbar;
% 变化检测结果
subplot(2,2,4), imshow(change_map), title('变化检测结果');
colormap(gray);
end
% 保存结果
if params.saveResults
[~, name1] = fileparts(uigetfile('last used'));
timestamp = datestr(now, 'yyyymmdd_HHMMSS');
output_dir = pwd;
% 保存变化图
imwrite(change_map, fullfile(output_dir, ['change_map_' timestamp '.png']));
% 保存变化幅度图
imwrite(mat2gray(magnitude), fullfile(output_dir, ['magnitude_' timestamp '.png']));
disp(['结果已保存至: ' output_dir]);
end
end
function export_statistics(change_map)
% 导出变化统计信息
total_pixels = numel(change_map);
changed_pixels = sum(change_map(:));
change_percent = (changed_pixels / total_pixels) * 100;
fprintf('\n===== 变化统计 =====\n');
fprintf('总像素数: %d\n', total_pixels);
fprintf('变化像素数: %d (%.2f%%)\n', changed_pixels, change_percent);
fprintf('未变化像素数: %d (%.2f%%)\n', total_pixels - changed_pixels, 100 - change_percent);
% 可选:保存统计信息到文件
stats_file = fopen('change_stats.txt', 'w');
fprintf(stats_file, '变化检测统计报告\n');
fprintf(stats_file, '生成时间: %s\n\n', datestr(now));
fprintf(stats_file, '总像素数: %d\n', total_pixels);
fprintf(stats_file, '变化像素数: %d (%.2f%%)\n', changed_pixels, change_percent);
fclose(stats_file);
end
程序特点与功能:
- 模块化设计 :
- 分离了影像加载、预处理、CVA计算、阈值分割和后处理模块
- 每个功能都有独立的函数实现
- 增强的预处理 :
- 支持波段选择(可指定特定波段参与计算)
- 自动尺寸检查和错误处理
- 可选的直方图匹配(注释部分)
- 灵活的阈值处理 :
- 支持Otsu自动阈值和手动阈值两种模式
- 阈值参数可通过结构体配置
- 高级后处理 :
- 形态学开闭运算去除噪声
- 面积过滤移除小区域(<50像素)
- 可调节的结构元素大小
- 全面的结果输出 :
- 可视化显示原始影像、变化幅度和检测结果
- 自动保存结果图像(PNG格式)
- 生成变化统计报告(文本文件)
- 控制台输出变化百分比
- 用户友好特性 :
- 交互式文件选择对话框
- 详细的错误处理和信息提示
- 时间戳命名防止覆盖
使用示例:
matlab
% 基本使用
change_detection_cva();
% 自定义参数(通过修改params结构体)
function custom_cva()
params = struct();
params.useAutoThreshold = false; % 使用手动阈值
params.manualThreshold = 0.3; % 设置阈值
params.morphologyEnabled = true; % 启用形态学处理
params.structElementRadius = 2; % 较小的结构元素
params.saveResults = true; % 保存结果
params.showPlots = true; % 显示图像
params.bandSelection = [3,2,1]; % 选择RGB波段(假设原图为多波段)
% 调用修改后的处理函数(需要稍作调整)
% ...
end
参考代码 cva变化检测程序 www.youwenfan.com/contentcss/55106.html
建议:
-
影像预处理:
- 确保影像经过精确配准
- 进行辐射定标和大气校正
- 对于高分辨率影像,考虑使用PCA降维
-
参数优化:
matlab% 尝试不同阈值策略 thresholds = 0.1:0.05:0.5; for t = thresholds params.manualThreshold = t; % 运行检测并记录结果 end % 尝试不同结构元素 radii = 1:5; for r = radii params.structElementRadius = r; % 运行检测 end -
结果验证:
- 使用混淆矩阵评估检测精度
- 结合实地调查数据进行验证
- 尝试不同波段组合(如NDVI、NDWI等指数)
-
性能优化:
- 对于大型影像,使用块处理
- 利用并行计算(
parfor) - 使用GPU加速(需要Parallel Computing Toolbox)