HyperAI超神经

使用 MATLAB 进行图像去雾处理

图像去雾处理 – Retinex 算法

一、教程简介

在计算机视觉领域,图像去雾是一项重要的预处理任务,尤其是在自动驾驶、遥感图像分析以及监控系统中,去雾能够有效提升图像质量,使目标更加清晰可见。本项目采用 Retinex 算法进行图像去雾,并结合 GPU 加速以提高计算效率。

本教程使用软件镜像为 MATLAB,算力资源为 RTX 4090 。

二、理论基础

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) 通过该方法,可以增强图像的对比度,同时减少光照影响。

三、操作步骤

1. 运行准备

克隆并成功启动容器后,打开工作空间。

  • 软件镜像为 MATLAB,算力资源为 RTX 4090,接入方式为「工作空间」。
3

2. 加载图像

在「工作空间」的「控制台」处找到「Matlab」,输入以下代码:
(本教程已在 home 目录给出示例图像「1.png」,直接输入代码即可)

f = imread('1.png');
imshow(f);
title('原始图像');
4
7

3. 运行去雾算法

代码实现(此处已将 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

4. 运行去雾处理

继续「Matlab」控制台中输入以下命令运行去雾处理:

In = RemoveFogByRetinex(f, 1);
8

5. 进一步增强对比度

继续「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);
9