在计算机视觉领域,图像去雾是一项重要的预处理任务,尤其是在自动驾驶、遥感图像分析以及监控系统中,去雾能够有效提升图像质量,使目标更加清晰可见。本项目采用 Retinex 算法进行图像去雾,并结合 GPU 加速以提高计算效率。
Retinex 算法原理:
Retinex (Retina + Cortex) 是 Land 和 McCann 提出的图像增强算法,主要基于人眼视觉系统对亮度变化的适应性。Retinex 算法的核心思想是:
- 分解反射和光照:图像 I(x, y)由光照 L(x, y) 和反射率 R(x, y) 组成,即: I(x, y) = R(x, y) * L(x, y)
- 对数变换:为了消除光照影响,取对数: log I(x, y) = log R(x, y) + log L(x, y)
- 平滑光照:使用高斯滤波 G(x, y) 估计光照分量: L'(x, y) = G(x, y) * I(x, y)
- 计算 Retinex 输出: R'(x, y) = log I(x, y) - log L'(x, y) 通过该方法,可以增强图像的对比度,同时减少光照影响。
教程链接:https://go.openbayes.com/vaEyL
使用云平台:OpenBayes
http://openbayes.com/console/signup?r=sony_0m6v
运行准备
登录 http://OpenBayes.com,在「公共教程」页面,选择键部署 「使用 MATLAB 进行图像去雾处理」教程。

页面跳转后,点击右上角「克隆」,将该教程克隆至自己的容器中。

选择「NVIDIA GeForce RTX 4090」以及「MATLAB」镜像,OpenBayes 平台提供了 4 种计费方式,大家可以按照需求选择「按量付费」或「包日/周/月」,点击「继续执行」。可以使用文章开头的邀请链接,获得 RTX 4090 使用时长!


待系统分配好资源,当状态变为「运行中」后,点击「打开工作空间」。


加载图像
在「工作空间」的「控制台」处找到「Matlab」,运行以下代码:
f = imread('1.png');
imshow(f);
title('原始图像');


运行去雾算法
代码实现(此处已将 RemoveFogByRetinex.m 代码文件准备完毕,已保存在 home 目录下,可以直接在下一步使用运行)
function In = RemoveFogByRetinex_GPU(f, flag)
% 启用CUDA前向兼容性
parallel.gpu.enableCUDAForwardCompatibility(true);
if nargin < 2
flag = 1;
end
% 转换到 GPU
f = gpuArray(im2double(f));
% 拆分颜色通道
fr = f(:, :, 1);
fg = f(:, :, 2);
fb = f(:, :, 3);
% 归一化
mr = mat2gray(fr);
mg = mat2gray(fg);
mb = mat2gray(fb);
% 设置滤波参数
alpha = 200;
n = floor(min([size(f, 1) size(f, 2)]) * 0.5);
n1 = floor((n + 1) / 2);
% 创建滤波核
[X, Y] = meshgrid(1:n, 1:n);
b = exp(-((X - n1).^2 + (Y - n1).^2) / (4 * alpha)) / (pi * alpha);
b = gpuArray(b);
% 进行滤波
nr1 = imfilter(mr, b, 'conv', 'replicate');
ng1 = imfilter(mg, b, 'conv', 'replicate');
nb1 = imfilter(mb, b, 'conv', 'replicate');
% 计算 Retinex 公式(避免 log(0) 问题)
ur1 = log(max(nr1, 0.01));
ug1 = log(max(ng1, 0.01));
ub1 = log(max(nb1, 0.01));
tr1 = log(max(mr, 0.01));
tg1 = log(max(mg, 0.01));
tb1 = log(max(mb, 0.01));
% 计算 Retinex 输出
yr1 = tr1 - ur1;
yg1 = tg1 - ug1;
yb1 = tb1 - ub1;
% 归一化(手动调整范围)
min_val = min([min(yr1(:)), min(yg1(:)), min(yb1(:))]);
max_val = max([max(yr1(:)), max(yg1(:)), max(yb1(:))]);
yr1 = (yr1 - min_val) / (max_val - min_val);
yg1 = (yg1 - min_val) / (max_val - min_val);
yb1 = (yb1 - min_val) / (max_val - min_val);
% 转换到 uint8
cr = gather(im2uint8(yr1));
cg = gather(im2uint8(yg1));
cb = gather(im2uint8(yb1));
% 合并通道
In = cat(3, cr, cg, cb);
% 显示结果
if flag
figure;
subplot(2, 2, 1);
imshow(gather(f)); title('原图像', 'FontWeight', 'Bold');
subplot(2, 2, 2);
imshow(In); title('处理后的图像', 'FontWeight', 'Bold');
Q = rgb2gray(gather(f));
M = rgb2gray(In);
subplot(2, 2, 3);
imhist(Q, 64); title('原灰度直方图', 'FontWeight', 'Bold');
subplot(2, 2, 4);
imhist(M, 64); title('处理后的灰度直方图', 'FontWeight', 'Bold');
end
end

运行去雾处理
继续在「Matlab」控制台中输入以下命令运行去雾处理:
In = RemoveFogByRetinex(f, 1);

进一步增强对比度
继续在「Matlab」控制台中输入以下命令进一步增强对比度:
lab = rgb2lab(In);
L = lab(:, :, 1) / 100;
L = adapthisteq(L, 'ClipLimit', 0.02, 'Distribution', 'rayleigh');
lab(:, :, 1) = L * 100;
In = lab2rgb(lab);
In = imadjust(In, stretchlim(In, [0.01, 0.99]), []);
In = imsharpen(In, 'Radius', 2, 'Amount', 1.5);
imshow(In);
