首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于MATLAB的CNN大气散射传播率计算与图像去雾实现

基于MATLAB的CNN大气散射传播率计算与图像去雾实现

原创
作者头像
用户11823301
发布2025-09-05 09:59:32
发布2025-09-05 09:59:32
1600
举报

通过CNN计算大气散射模型中的透射率来实现图像去雾,是融合物理模型与深度学习的有效方法。

基于CNN和大气散射模型的图像去雾

1 大气散射模型

大气散射模型是描述雾天图像成像过程的物理模型,其数学表达式为:

I(x) = J(x)t(x) + A(1-t(x))

其中:

  • I(x) 表示观测到的有雾图像
  • J(x) 表示要恢复的无雾图像
  • t(x) 表示透射率(介质传输率),描述光在空气中传播时的衰减程度
  • A 表示全局大气光值

图像去雾的核心任务就是从有雾图像I(x)中估计出透射率t(x)和大气光值A,然后通过逆运算恢复无雾图像J(x)

J(x) = \frac{I(x) - A}{t(x)} + A

传统方法需要人工设计特征和先验(如暗通道先验、颜色衰减先验)来估计t(x)A,但在复杂场景下往往表现不佳。

2 CNN在透射率估计中的应用

卷积神经网络(CNN)能够自动学习图像特征,非常适合用于估计透射率。其主要优势在于:

  • 自动学习特征,避免人工先验的局限性
  • 能更好地处理复杂场景(如天空、白色物体等)
  • 估计的透射率图通常具有更好的边缘保持特性

2.1 网络设计选择

用于透射率估计的CNN通常采用编码器-解码器(Encoder-Decoder)结构,有时会加入跳跃连接(Skip Connections) 来融合低层和高层特征。

一个简单的网络结构示例:

  1. 编码器:使用卷积层和池化层逐步提取图像特征并减小空间尺寸
  2. 解码器:使用转置卷积或上采样层逐步恢复空间尺寸,输出单通道透射率图
  3. 跳跃连接:将编码器中的特征与解码器中相应尺度的特征连接,帮助保留细节

2.2 损失函数设计

训练CNN估计透射率时,常用的损失函数包括:

  • 均方误差(MSE)损失:直接比较预测透射率与真实透射率的差异
  • 结构相似性(SSIM)损失:考虑图像的结构信息,有助于保持边缘和结构
  • 复合损失:结合MSE和SSIM的优点

3 MATLAB实现指南

3.1 数据准备

首先需要准备有雾图像和对应的真实透射率图数据集用于训练。由于真实透射率难以获取,通常使用合成数据集,如NYU Depth数据集和RESIDE数据集。

代码语言:matlab
复制
% 示例代码:加载和预处理数据
imds = imageDatastore('hazy_images_folder');
pxds = imageDatastore('transmission_maps_folder', 'ReadFcn', @(filename) im2gray(imread(filename)));
​
% 将图像和透射率图组合为训练数据
trainingData = combine(imds, pxds);

3.2 网络结构定义

在MATLAB中定义一个简单的编码器-解码器网络:

代码语言:matlab
复制
function lgraph = createTransmissionNet(inputSize)
% 创建编码器-解码器网络用于透射率估计
​
    layers = [
        imageInputLayer(inputSize, 'Name', 'input')
        
        % 编码器
        convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv1')
        reluLayer('Name', 'relu1')
        maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool1')
        
        convolution2dLayer(3, 128, 'Padding', 'same', 'Name', 'conv2')
        reluLayer('Name', 'relu2')
        maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool2')
        
        convolution2dLayer(3, 256, 'Padding', 'same', 'Name', 'conv3')
        reluLayer('Name', 'relu3')
        
        % 解码器
        transposedConv2dLayer(2, 128, 'Stride', 2, 'Name', 'tconv1')
        reluLayer('Name', 'relu4')
        
        transposedConv2dLayer(2, 64, 'Stride', 2, 'Name', 'tconv2')
        reluLayer('Name', 'relu5')
        
        convolution2dLayer(3, 1, 'Padding', 'same', 'Name', 'final_conv')
        sigmoidLayer('Name', 'sigmoid')  % 透射率值应在0-1之间
    ];
    
    lgraph = layerGraph(layers);
end

3.3 模型训练

配置训练选项并进行模型训练:

代码语言:matlab
复制
% 定义训练选项
options = trainingOptions('adam', ...
    'InitialLearnRate', 1e-4, ...
    'MaxEpochs', 30, ...
    'MiniBatchSize', 8, ...
    'Shuffle', 'every-epoch', ...
    'Plots', 'training-progress', ...
    'Verbose', false);
​
% 训练网络
net = trainNetwork(trainingData, lgraph, options);

3.4 大气光值估计

大气光值A通常可以通过选取有雾图像中最亮像素或结合透射率图来估计:

代码语言:matlab
复制
function A = estimateAtmosphericLight(hazyImage, transmissionMap)
% 估计大气光值
% 选择透射率最低的像素(雾最浓的区域)对应的有雾图像中最亮的像素
​
    [height, width] = size(transmissionMap);
    numPixels = height * width;
    numTopPixels = max(1, round(0.001 * numPixels));  % 前0.1%的像素
    
    % 将透射率图转换为向量并排序
    transmissionVector = reshape(transmissionMap, numPixels, 1);
    [~, sortedIndices] = sort(transmissionVector);
    
    % 选择透射率最低的像素
    darkestIndices = sortedIndices(1:numTopPixels);
    
    % 找到有雾图像中这些像素最亮的强度
    hazyVector = reshape(hazyImage, numPixels, 3);
    darkestPixels = hazyVector(darkestIndices, :);
    
    % 取这些像素中最亮的作为大气光值
    A = max(darkestPixels, [], 1);
end

3.5 图像复原

使用估计的透射率图和大气光值进行图像复原:

代码语言:matlab
复制
function dehazedImage = recoverImage(hazyImage, transmissionMap, A)
% 根据大气散射模型恢复无雾图像
​
    % 确保透射率不会太小(避免除零和噪声放大)
    t = max(transmissionMap, 0.1);
    
    % 扩展透射率图到三通道
    t = repmat(t, [1, 1, 3]);
    
    % 根据大气散射模型复原图像
    dehazedImage = (hazyImage - A) ./ t + A;
    
    % 确保像素值在有效范围内
    dehazedImage = max(min(dehazedImage, 1), 0);
end

3.6 完整流程

代码语言:matlab
复制
% 加载有雾图像
hazyImage = im2double(imread('hazy_image.jpg'));
​
% 使用训练好的网络估计透射率
transmissionMap = predict(net, hazyImage);
​
% 估计大气光值
A = estimateAtmosphericLight(hazyImage, transmissionMap);
​
% 复原图像
dehazedImage = recoverImage(hazyImage, transmissionMap, A);
​
% 显示结果
figure;
subplot(1, 3, 1); imshow(hazyImage); title('有雾图像');
subplot(1, 3, 2); imshow(transmissionMap); title('估计的透射率图');
subplot(1, 3, 3); imshow(dehazedImage); title('去雾结果');

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于CNN和大气散射模型的图像去雾
    • 1 大气散射模型
    • 2 CNN在透射率估计中的应用
      • 2.1 网络设计选择
      • 2.2 损失函数设计
    • 3 MATLAB实现指南
      • 3.1 数据准备
      • 3.2 网络结构定义
      • 3.3 模型训练
      • 3.4 大气光值估计
      • 3.5 图像复原
      • 3.6 完整流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档