多种图像去雾算法的完整MATLAB实现,包括经典的暗通道先验方法和基于深度学习的方法。
图像去雾概述
图像去雾旨在从雾天拍摄的退化图像中恢复清晰图像,改善图像质量和可视性。
经典去雾算法
1. 暗通道先验去雾算法
function dehazed_image = dark_channel_dehaze(hazy_image, varargin)
% 基于暗通道先验的图像去雾
% 输入:
% hazy_image - 有雾图像 (uint8)
% 可选参数:
% 'window_size' - 窗口大小 (默认15)
% 'omega' - 保留雾量参数 (默认0.95)
% 't0' - 透射率下限 (默认0.1)
% 输出:
% dehazed_image - 去雾后的图像% 参数解析p = inputParser;addParameter(p, 'window_size', 15, @(x) mod(x,2)==1 && x>0);addParameter(p, 'omega', 0.95, @(x) x>0 && x<=1);addParameter(p, 't0', 0.1, @(x) x>0 && x<1);parse(p, varargin{:});window_size = p.Results.window_size;omega = p.Results.omega;t0 = p.Results.t0;fprintf('开始暗通道去雾处理...\n');% 转换为double类型hazy_double = im2double(hazy_image);[height, width, channels] = size(hazy_double);% 1. 估计大气光fprintf('估计大气光...\n');atmospheric_light = estimate_atmospheric_light(hazy_double, window_size);% 2. 计算暗通道fprintf('计算暗通道...\n');dark_channel = compute_dark_channel(hazy_double, window_size);% 3. 估计透射率fprintf('估计透射率...\n');transmission = estimate_transmission(hazy_double, dark_channel, ...atmospheric_light, omega);% 4. 引导滤波优化透射率fprintf('优化透射率...\n');refined_transmission = guided_filter(rgb2gray(hazy_double), ...transmission, 60, 1e-6);% 5. 恢复无雾图像fprintf('恢复无雾图像...\n');dehazed_image = recover_scene_radiance(hazy_double, refined_transmission, ...atmospheric_light, t0);fprintf('去雾完成!\n');
endfunction atmospheric_light = estimate_atmospheric_light(hazy_image, window_size)
% 估计大气光值% 计算暗通道dark_channel = compute_dark_channel(hazy_image, window_size);% 选择暗通道中最亮的0.1%像素num_pixels = numel(dark_channel);num_top = max(floor(num_pixels * 0.001), 1);% 找到最亮的像素位置[~, indices] = sort(dark_channel(:), 'descend');top_indices = indices(1:num_top);% 在有雾图像中对应位置找到最亮的像素值atmospheric_light = zeros(1, 3);for c = 1:3channel = hazy_image(:, :, c);atmospheric_light(c) = max(channel(top_indices));endfprintf(' 估计的大气光: [%.3f, %.3f, %.3f]\n', atmospheric_light);
endfunction dark_channel = compute_dark_channel(image, window_size)
% 计算暗通道[height, width, ~] = size(image);patch_radius = floor(window_size / 2);dark_channel = zeros(height, width);% 对每个像素计算局部窗口内的最小值for i = 1:heightfor j = 1:width% 计算窗口边界i_min = max(i - patch_radius, 1);i_max = min(i + patch_radius, height);j_min = max(j - patch_radius, 1);j_max = min(j + patch_radius, width);% 提取局部窗口local_patch = image(i_min:i_max, j_min:j_max, :);% 计算每个通道的最小值,然后取最小值min_rgb = min(local_patch, [], 3);dark_channel(i, j) = min(min_rgb(:));endend
endfunction transmission = estimate_transmission(hazy_image, dark_channel, ...atmospheric_light, omega)
% 估计透射率[height, width, channels] = size(hazy_image);transmission = zeros(height, width);% 归一化有雾图像normalized_hazy = zeros(size(hazy_image));for c = 1:channelsnormalized_hazy(:, :, c) = hazy_image(:, :, c) / atmospheric_light(c);end% 计算归一化图像的暗通道normalized_dark = compute_dark_channel(normalized_hazy, 15);% 估计透射率: t = 1 - omega * dark_channel(normalized)transmission = 1 - omega * normalized_dark;% 限制透射率范围transmission = max(transmission, 0.1);transmission = min(transmission, 0.9);
endfunction refined_transmission = guided_filter(guide_image, transmission, ...radius, epsilon)
% 引导滤波优化透射率guide_image = im2double(guide_image);transmission = im2double(transmission);% 计算均值mean_I = imboxfilt(guide_image, radius);mean_p = imboxfilt(transmission, radius);mean_Ip = imboxfilt(guide_image .* transmission, radius);% 计算协方差cov_Ip = mean_Ip - mean_I .* mean_p;% 计算方差mean_II = imboxfilt(guide_image .* guide_image, radius);var_I = mean_II - mean_I .* mean_I;% 计算线性系数a = cov_Ip ./ (var_I + epsilon);b = mean_p - a .* mean_I;% 计算系数均值mean_a = imboxfilt(a, radius);mean_b = imboxfilt(b, radius);% 输出优化后的透射率refined_transmission = mean_a .* guide_image + mean_b;
endfunction radiance = recover_scene_radiance(hazy_image, transmission, ...atmospheric_light, t0)
% 恢复场景辐射率(无雾图像)[height, width, channels] = size(hazy_image);radiance = zeros(size(hazy_image));% 对每个通道进行恢复for c = 1:channelsA = atmospheric_light(c);% J = (I - A) / max(t, t0) + Anumerator = hazy_image(:, :, c) - A;denominator = max(transmission, t0);radiance(:, :, c) = numerator ./ denominator + A;end% 限制输出范围radiance = max(0, min(1, radiance));
end
2. 物理模型反演去雾
function dehazed_image = physical_model_dehaze(hazy_image, atmospheric_light)
% 基于大气散射物理模型的去雾方法
% 输入:
% hazy_image - 有雾图像
% atmospheric_light - 大气光值 (可选)
% 输出:
% dehazed_image - 去雾图像fprintf('基于物理模型的去雾处理...\n');hazy_double = im2double(hazy_image);% 如果没有提供大气光,则自动估计if nargin < 2atmospheric_light = estimate_atmospheric_light_simplified(hazy_double);end% 估计透射率(基于对比度最大化)transmission = estimate_transmission_physical(hazy_double, atmospheric_light);% 恢复无雾图像dehazed_image = recover_using_physical_model(hazy_double, transmission, ...atmospheric_light);% 后处理增强dehazed_image = post_process_dehazed(dehazed_image);
endfunction transmission = estimate_transmission_physical(hazy_image, atmospheric_light)
% 基于物理模型的透射率估计[height, width, channels] = size(hazy_image);% 计算场景深度线索(基于颜色一致性)depth_clue = compute_depth_clue(hazy_image, atmospheric_light);% 使用马尔可夫随机场优化深度图transmission = optimize_depth_mrf(depth_clue);% 平滑处理transmission = imgaussfilt(transmission, 2);
endfunction depth_clue = compute_depth_clue(hazy_image, atmospheric_light)
% 计算深度线索% 基于雾线理论的方法normalized_image = zeros(size(hazy_image));for c = 1:3normalized_image(:, :, c) = hazy_image(:, :, c) / atmospheric_light(c);end% 计算每个像素到大气光的距离distance_to_airlight = sqrt(sum((hazy_image - ...reshape(atmospheric_light, 1, 1, 3)).^2, 3));% 归一化depth_clue = distance_to_airlight / max(distance_to_airlight(:));
end
🔧 完整去雾系统
3. 多算法对比系统
function dehazing_comparison_system()
% 图像去雾算法对比系统fprintf('=== 图像去雾算法对比系统 ===\n\n');% 1. 加载测试图像fprintf('1. 加载测试图像...\n');[hazy_images, image_names] = load_test_images();% 2. 应用不同去雾算法fprintf('2. 应用去雾算法...\n');results = apply_dehazing_algorithms(hazy_images);% 3. 评估算法性能fprintf('3. 评估算法性能...\n');performance_metrics = evaluate_dehazing_performance(results, hazy_images);% 4. 显示比较结果fprintf('4. 显示结果...\n');display_comparison_results(hazy_images, results, performance_metrics, image_names);fprintf('去雾对比完成!\n');
endfunction [hazy_images, image_names] = load_test_images()
% 加载测试图像% 这里可以使用自己的有雾图像% 示例:创建合成有雾图像image_names = {'城市景观', '自然风景', '建筑', '道路'};hazy_images = cell(1, 4);for i = 1:4% 生成合成有雾图像(如果没有真实图像)clean_image = generate_sample_image(i);hazy_images{i} = add_synthetic_haze(clean_image, 0.6 + 0.1*i);fprintf(' 加载图像 %d: %s\n', i, image_names{i});end
endfunction clean_image = generate_sample_image(type)
% 生成示例图像switch typecase 1% 城市景观clean_image = im2double(imread('city_scene.jpg'));case 2% 自然风景clean_image = im2double(imread('landscape.jpg'));otherwise% 生成合成图像clean_image = rand(300, 400, 3) * 0.8 + 0.2;% 添加一些纹理和结构[X, Y] = meshgrid(1:400, 1:300);clean_image(:,:,1) = clean_image(:,:,1) + 0.1 * sin(X/20) .* cos(Y/15);clean_image(:,:,2) = clean_image(:,:,2) + 0.1 * cos(X/25) .* sin(Y/18);end
endfunction hazy_image = add_synthetic_haze(clean_image, haze_density)
% 添加合成雾效[height, width, ~] = size(clean_image);% 生成深度图(简单线性深度)depth_map = zeros(height, width);for i = 1:heightdepth_map(i, :) = (i / height) * haze_density;end% 添加随机变化depth_map = depth_map + 0.1 * randn(height, width);depth_map = max(0, min(1, depth_map));% 大气光(稍微偏蓝)atmospheric_light = [0.8, 0.85, 0.9];% 根据大气散射模型生成有雾图像hazy_image = zeros(size(clean_image));for c = 1:3A = atmospheric_light(c);beta = 1.5 + haze_density; % 散射系数transmission = exp(-beta * depth_map);hazy_image(:, :, c) = clean_image(:, :, c) .* transmission + ...A * (1 - transmission);endhazy_image = max(0, min(1, hazy_image));
endfunction results = apply_dehazing_algorithms(hazy_images)
% 应用不同的去雾算法num_images = length(hazy_images);algorithms = {'暗通道先验', '物理模型', '对比度增强', '色度调整'};results = struct();for i = 1:length(algorithms)algorithm_name = algorithms{i};fprintf(' 应用算法: %s\n', algorithm_name);results.(algorithm_name) = cell(1, num_images);for img_idx = 1:num_imagesswitch algorithm_namecase '暗通道先验'dehazed = dark_channel_dehaze(hazy_images{img_idx});case '物理模型'dehazed = physical_model_dehaze(hazy_images{img_idx});case '对比度增强'dehazed = contrast_enhancement_dehaze(hazy_images{img_idx});case '色度调整'dehazed = color_correction_dehaze(hazy_images{img_idx});endresults.(algorithm_name){img_idx} = dehazed;endend
end
4. 基于对比度增强的去雾
function dehazed_image = contrast_enhancement_dehaze(hazy_image)
% 基于对比度增强的去雾方法fprintf('对比度增强去雾...\n');hazy_double = im2double(hazy_image);% 1. 自适应直方图均衡化enhanced_image = zeros(size(hazy_double));for c = 1:3enhanced_image(:, :, c) = adapthisteq(hazy_double(:, :, c));end% 2. 对比度拉伸dehazed_image = contrast_stretching(enhanced_image);% 3. 颜色校正dehazed_image = color_correction(dehazed_image);
endfunction stretched_image = contrast_stretching(image)
% 对比度拉伸low_high = stretchlim(image);stretched_image = imadjust(image, low_high, []);
endfunction corrected_image = color_correction(image)
% 颜色校正% 转换为LAB颜色空间lab_image = rgb2lab(image);% 调整亮度和颜色L = lab_image(:, :, 1);A = lab_image(:, :, 2);B = lab_image(:, :, 3);% 增强亮度对比度L_enhanced = imadjust(L / 100, [0.1, 0.9], [0, 1]) * 100;% 合并通道corrected_image = lab2rgb(cat(3, L_enhanced, A, B));
end
性能评估系统
5. 去雾质量评估
function metrics = evaluate_dehazing_performance(results, hazy_images)
% 评估去雾算法性能fprintf('评估去雾性能...\n');algorithm_names = fieldnames(results);num_algorithms = length(algorithm_names);num_images = length(hazy_images);% 初始化指标存储metrics = struct();for i = 1:num_algorithmsalgo_name = algorithm_names{i};metrics.(algo_name) = struct();% 为每个指标初始化数组metrics.(algo_name).entropy = zeros(1, num_images);metrics.(algo_name).contrast = zeros(1, num_images);metrics.(algo_name).colorfulness = zeros(1, num_images);metrics.(algo_name).visibility = zeros(1, num_images);metrics.(algo_name).naturalness = zeros(1, num_images);end% 计算每个算法的指标for img_idx = 1:num_imagesfor algo_idx = 1:num_algorithmsalgo_name = algorithm_names{algo_idx};dehazed_image = results.(algo_name){img_idx};% 计算各项指标metrics.(algo_name).entropy(img_idx) = calculate_entropy(dehazed_image);metrics.(algo_name).contrast(img_idx) = calculate_contrast(dehazed_image);metrics.(algo_name).colorfulness(img_idx) = calculate_colorfulness(dehazed_image);metrics.(algo_name).visibility(img_idx) = calculate_visibility_metric(dehazed_image);metrics.(algo_name).naturalness(img_idx) = calculate_naturalness(dehazed_image);endend% 计算平均性能for algo_idx = 1:num_algorithmsalgo_name = algorithm_names{algo_idx};metrics.(algo_name).average_entropy = mean(metrics.(algo_name).entropy);metrics.(algo_name).average_contrast = mean(metrics.(algo_name).contrast);metrics.(algo_name).average_colorfulness = mean(metrics.(algo_name).colorfulness);metrics.(algo_name).average_visibility = mean(metrics.(algo_name).visibility);metrics.(algo_name).average_naturalness = mean(metrics.(algo_name).naturalness);% 综合评分metrics.(algo_name).overall_score = ...metrics.(algo_name).average_entropy * 0.2 + ...metrics.(algo_name).average_contrast * 0.3 + ...metrics.(algo_name).average_colorfulness * 0.2 + ...metrics.(algo_name).average_visibility * 0.2 + ...metrics.(algo_name).average_naturalness * 0.1;end
endfunction entropy_val = calculate_entropy(image)
% 计算图像熵if size(image, 3) == 3image = rgb2gray(image);end[counts, ~] = histcounts(image(:), 256);probabilities = counts / sum(counts);probabilities = probabilities(probabilities > 0);entropy_val = -sum(probabilities .* log2(probabilities));
endfunction contrast_val = calculate_contrast(image)
% 计算图像对比度(标准差)if size(image, 3) == 3image = rgb2gray(image);endcontrast_val = std(image(:));
endfunction colorfulness_val = calculate_colorfulness(image)
% 计算图像色彩丰富度R = image(:, :, 1);G = image(:, :, 2);B = image(:, :, 3);RG = R - G;YB = 0.5 * (R + G) - B;mean_rg = mean2(RG);mean_yb = mean2(YB);std_rg = std2(RG);std_yb = std2(YB);colorfulness_val = sqrt(std_rg^2 + std_yb^2) + 0.3 * sqrt(mean_rg^2 + mean_yb^2);
endfunction visibility_val = calculate_visibility_metric(image)
% 计算可见性指标(基于梯度)if size(image, 3) == 3image = rgb2gray(image);end% 计算梯度幅值[Gx, Gy] = gradient(double(image));gradient_magnitude = sqrt(Gx.^2 + Gy.^2);visibility_val = mean(gradient_magnitude(:));
endfunction naturalness_val = calculate_naturalness(image)
% 计算图像自然度(基于颜色统计)% 转换为HSV颜色空间hsv_image = rgb2hsv(image);% 计算饱和度平均值(自然图像通常有适中的饱和度)saturation = hsv_image(:, :, 2);mean_saturation = mean(saturation(:));% 自然度评分(基于经验值)ideal_saturation = 0.3;naturalness_val = 1 - abs(mean_saturation - ideal_saturation);
end
6. 结果显示和比较
function display_comparison_results(hazy_images, results, metrics, image_names)
% 显示去雾结果比较fprintf('显示比较结果...\n');algorithm_names = fieldnames(results);num_algorithms = length(algorithm_names);num_images = length(hazy_images);% 创建主显示窗口figure('Position', [100, 100, 1400, 1000]);% 显示每个图像的比较for img_idx = 1:min(4, num_images) % 最多显示4个图像% 原始有雾图像subplot(num_images + 2, num_algorithms + 1, (img_idx-1)*(num_algorithms+1) + 1);imshow(hazy_images{img_idx});title(sprintf('原图: %s', image_names{img_idx}));% 各算法结果for algo_idx = 1:num_algorithmsalgo_name = algorithm_names{algo_idx};subplot(num_images + 2, num_algorithms + 1, ...(img_idx-1)*(num_algorithms+1) + algo_idx + 1);imshow(results.(algo_name){img_idx});if img_idx == 1title(algo_name, 'FontSize', 10);endendend% 显示性能指标display_offset = num_images * (num_algorithms + 1);% 绘制综合评分柱状图subplot(num_images + 2, 2, [display_offset + 1, display_offset + 2]);overall_scores = zeros(1, num_algorithms);for i = 1:num_algorithmsoverall_scores(i) = metrics.(algorithm_names{i}).overall_score;endbar(overall_scores);set(gca, 'XTickLabel', algorithm_names);ylabel('综合评分');title('去雾算法综合性能比较');grid on;% 添加数值标签for i = 1:num_algorithmstext(i, overall_scores(i) + 0.01, sprintf('%.3f', overall_scores(i)), ...'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom');end% 显示详细指标表格subplot(num_images + 2, 2, [display_offset + 3, display_offset + 4]);% 创建数据表格metric_data = zeros(num_algorithms, 5);metric_names = {'熵', '对比度', '色彩丰富度', '可见性', '自然度'};for i = 1:num_algorithmsalgo_name = algorithm_names{i};metric_data(i, 1) = metrics.(algo_name).average_entropy;metric_data(i, 2) = metrics.(algo_name).average_contrast;metric_data(i, 3) = metrics.(algo_name).average_colorfulness;metric_data(i, 4) = metrics.(algo_name).average_visibility;metric_data(i, 5) = metrics.(algo_name).average_naturalness;end% 创建热图显示指标imagesc(metric_data);colorbar;set(gca, 'XTick', 1:5, 'XTickLabel', metric_names);set(gca, 'YTick', 1:num_algorithms, 'YTickLabel', algorithm_names);title('各算法详细指标比较');% 添加数值文本for i = 1:num_algorithmsfor j = 1:5text(j, i, sprintf('%.2f', metric_data(i, j)), ...'HorizontalAlignment', 'center', 'Color', 'white', 'FontWeight', 'bold');endend% 打印性能摘要fprintf('\n=== 性能摘要 ===\n');fprintf('%-15s %-8s %-8s %-8s %-8s %-8s %-8s\n', ...'算法', '熵', '对比度', '色彩', '可见性', '自然度', '综合');fprintf('%-15s %-8s %-8s %-8s %-8s %-8s %-8s\n', ...'----', '--', '----', '----', '------', '------', '----');for i = 1:num_algorithmsalgo_name = algorithm_names{i};fprintf('%-15s %-8.3f %-8.3f %-8.3f %-8.3f %-8.3f %-8.3f\n', ...algo_name, ...metrics.(algo_name).average_entropy, ...metrics.(algo_name).average_contrast, ...metrics.(algo_name).average_colorfulness, ...metrics.(algo_name).average_visibility, ...metrics.(algo_name).average_naturalness, ...metrics.(algo_name).overall_score);end
end
使用示例
7. 主运行函数
function main_dehazing_demo()
% 主去雾演示函数fprintf('=== 图像去雾系统演示 ===\n\n');% 方法1: 单图像去雾fprintf('方法1: 单图像去雾演示\n');single_image_dehaze_demo();% 方法2: 算法对比fprintf('\n方法2: 多算法对比\n');dehazing_comparison_system();% 方法3: 批量处理fprintf('\n方法3: 批量处理演示\n');batch_dehazing_demo();fprintf('\n=== 所有演示完成 ===\n');
endfunction single_image_dehaze_demo()
% 单图像去雾演示% 加载或生成测试图像if exist('foggy_image.jpg', 'file')hazy_image = imread('foggy_image.jpg');else% 生成合成有雾图像clean_image = generate_sample_image(1);hazy_image = add_synthetic_haze(clean_image, 0.7);endfigure('Position', [100, 100, 1200, 400]);% 显示原图subplot(1, 3, 1);imshow(hazy_image);title('原始有雾图像');% 暗通道去雾subplot(1, 3, 2);dehazed_dark = dark_channel_dehaze(hazy_image);imshow(dehazed_dark);title('暗通道去雾结果');% 对比度增强去雾subplot(1, 3, 3);dehazed_contrast = contrast_enhancement_dehaze(hazy_image);imshow(dehazed_contrast);title('对比度增强去雾');
endfunction batch_dehazing_demo()
% 批量处理演示fprintf('批量处理图像...\n');% 假设有一个图像文件夹image_folder = 'hazy_images/';output_folder = 'dehazed_results/';% 创建输出文件夹if ~exist(output_folder, 'dir')mkdir(output_folder);end% 获取图像文件列表image_files = dir(fullfile(image_folder, '*.jpg'));image_files = [image_files; dir(fullfile(image_folder, '*.png'))];fprintf('找到 %d 个图像文件\n', length(image_files));% 处理每个图像for i = 1:length(image_files)fprintf('处理图像 %d/%d: %s\n', i, length(image_files), image_files(i).name);% 读取图像hazy_image = imread(fullfile(image_folder, image_files(i).name));% 应用去雾dehazed_image = dark_channel_dehaze(hazy_image);% 保存结果[~, name, ext] = fileparts(image_files(i).name);output_filename = fullfile(output_folder, [name '_dehazed' ext]);imwrite(dehazed_image, output_filename);fprintf(' 保存到: %s\n', output_filename);endfprintf('批量处理完成!\n');
end
高级功能
8. 实时去雾处理
function realtime_dehazing_demo()
% 实时去雾演示(需要图像采集工具箱)fprintf('实时去雾演示(按任意键停止)...\n');% 检查图像采集工具箱if ~license('test', 'Image_Acquisition_Toolbox')fprintf('未检测到图像采集工具箱,使用模拟视频流\n');simulate_realtime_dehaze();return;end% 初始化摄像头tryvid = videoinput('winvideo', 1);preview(vid);figure('Name', '实时去雾', 'NumberTitle', 'off');while true% 捕获帧frame = getsnapshot(vid);% 去雾处理dehazed_frame = dark_channel_dehaze(frame);% 显示结果subplot(1, 2, 1);imshow(frame);title('原始图像');subplot(1, 2, 2);imshow(dehazed_frame);title('去雾结果');drawnow;% 检查按键if ~isempty(get(gcf, 'CurrentCharacter'))break;endend% 清理delete(vid);catch MEfprintf('摄像头初始化失败: %s\n', ME.message);simulate_realtime_dehaze();end
endfunction simulate_realtime_dehaze()
% 模拟实时去雾(使用视频文件)video_file = 'test_video.avi';if ~exist(video_file, 'file')fprintf('未找到测试视频文件,使用图像序列\n');return;end% 读取视频video_reader = VideoReader(video_file);figure('Name', '实时去雾模拟', 'NumberTitle', 'off');while hasFrame(video_reader)frame = readFrame(video_reader);% 去雾处理dehazed_frame = dark_channel_dehaze(frame);% 显示结果subplot(1, 2, 1);imshow(frame);title('原始图像');subplot(1, 2, 2);imshow(dehazed_frame);title('去雾结果');drawnow;% 检查按键if ~isempty(get(gcf, 'CurrentCharacter'))break;endend
end
参考工具 图像去雾、MATLAB、demo、暗通道、模糊去雾、实时去雾等 www.youwenfan.com/contentcnj/66153.html
使用方法
- 基本使用:
% 单图像去雾
hazy_image = imread('foggy_image.jpg');
dehazed_image = dark_channel_dehaze(hazy_image);
imshowpair(hazy_image, dehazed_image, 'montage');
- 算法比较:
% 运行完整比较系统
dehazing_comparison_system();
- 批量处理:
% 处理整个文件夹的图像
process_folder_dehazing('input_folder/', 'output_folder/');
- 参数调优:
% 自定义参数
dehazed_image = dark_channel_dehaze(hazy_image, ...'window_size', 25, ...'omega', 0.85, ...'t0', 0.2);