近红外与可见光图像融合的多种方法实现

介绍七种不同的近红外(NIR)与可见光(RGB)图像融合方法 这些方法各具特点,适用于不同的场景。

核心融合方法 matlab

function fusedImage = fuseNIR_RGB(nirPath, rgbPath, method, varargin)
    % 读取图像
    nir = im2double(imread(nirPath));
    rgb = im2double(imread(rgbPath));
    
    % 确保图像尺寸一致
    if ~isequal(size(nir), size(rgb(:,:,1)))
        nir = imresize(nir, [size(rgb,1), size(rgb,2)]);
    end
    
    % 选择融合方法
    switch lower(method)
        case 'weighted_average'
            % 加权平均法
            alpha = 0.6; % NIR权重
            if nargin > 3, alpha = varargin{1}; end
            fusedImage = alpha * nir + (1-alpha) * mean(rgb, 3);
            
        case 'ihs'
            % IHS变换融合
            hsv = rgb2hsv(rgb);
            fusedImage = hsv;
            fusedImage(:,:,3) = nir; % 用NIR替换亮度分量
            fusedImage = hsv2rgb(fusedImage);
            
        case 'wavelet'
            % 小波变换融合
            level = 3; % 分解层数
            if nargin > 3, level = varargin{1}; end
            
            % 对每个通道分别处理
            fusedRGB = zeros(size(rgb));
            for c = 1:3
                [C_rgb, S] = wavedec2(rgb(:,:,c), level, 'db4');
                [C_nir, ~] = wavedec2(nir, level, 'db4');
                
                % 融合规则:低频取平均,高频取绝对值最大
                fusedCoeffs = zeros(size(C_rgb));
                for k = 1:level
                    % 低频系数
                    len = S(1,1)*S(1,2);
                    idx = 1:len;
                    fusedCoeffs(idx) = (C_rgb(idx) + C_nir(idx)) / 2;
                    
                    % 高频系数
                    for d = 1:3 % 水平、垂直、对角
                        startIdx = len + 1;
                        len = S(k+1,1)*S(k+1,2);
                        endIdx = startIdx + len - 1;
                        
                        % 取绝对值大的系数
                        abs_rgb = abs(C_rgb(startIdx:endIdx));
                        abs_nir = abs(C_nir(startIdx:endIdx));
                        mask = abs_rgb > abs_nir;
                        fusedCoeffs(startIdx:endIdx) = ...
                            mask.*C_rgb(startIdx:endIdx) + ...
                            ~mask.*C_nir(startIdx:endIdx);
                    end
                end
                fusedRGB(:,:,c) = waverec2(fusedCoeffs, S, 'db4');
            end
            fusedImage = fusedRGB;
            
        case 'pca'
            % PCA融合
            [height, width] = size(nir);
            dataMatrix = [nir(:), reshape(rgb, [height*width, 3])];
            [coeff, score, ~] = pca(dataMatrix);
            
            % 用第一主成分替换NIR通道
            fusedData = score * coeff';
            fusedImage = reshape(fusedData(:,2:end), [height, width, 3]);
            
        case 'laplacian'
            % 拉普拉斯金字塔融合
            levels = 5; % 金字塔层数
            if nargin > 3, levels = varargin{1}; end
            
            % 创建金字塔
            nirPyr = laplacianPyramid(nir, levels);
            rgbPyr = cell(1, levels);
            for c = 1:3
                rgbPyr{c} = laplacianPyramid(rgb(:,:,c), levels);
            end
            
            % 融合金字塔
            fusedPyr = cell(1, levels);
            for l = 1:levels
                if l == levels % 顶层(最低频)
                    fusedPyr{l} = (nirPyr{l} + mean(cat(3, rgbPyr{1}{l}, ...
                        rgbPyr{2}{l}, rgbPyr{3}{l}), 3)) / 2;
                else
                    % 高频层取绝对值大的系数
                    abs_nir = abs(nirPyr{l});
                    abs_rgb = mean(cat(3, abs(rgbPyr{1}{l}), ...
                        abs(rgbPyr{2}{l}), abs(rgbPyr{3}{l})), 3);
                    mask = abs_nir > abs_rgb;
                    fusedPyr{l} = mask.*nirPyr{l} + ~mask.*mean(cat(3, ...
                        rgbPyr{1}{l}, rgbPyr{2}{l}, rgbPyr{3}{l}), 3);
                end
            end
            
            % 重建融合图像
            fusedGray = reconstructPyramid(fusedPyr);
            fusedImage = rgb;
            for c = 1:3
                fusedImage(:,:,c) = imadjust(fusedImage(:,:,c), ...
                    stretchlim(fusedImage(:,:,c)), [0 1]);
            end
            fusedImage = fusedGray * 0.6 + fusedImage * 0.4;
            
        case 'guided_filter'
            % 导向滤波融合
            radius = 15; % 滤波器半径
            eps = 0.01; % 正则化参数
            if nargin > 3, radius = varargin{1}; end
            if nargin > 4, eps = varargin{2}; end
            
            fusedImage = rgb;
            for c = 1:3
                fusedImage(:,:,c) = imguidedfilter(rgb(:,:,c), nir, ...
                    'NeighborhoodSize', [radius, radius], 'DegreeOfSmoothing', eps);
            end
            
        case 'deep_learning'
            % 深度学习融合(需要深度学习工具箱)
            if ~license('test', 'Neural_Network_Toolbox')
                error('深度学习融合需要神经网络工具箱');
            end
            
            % 创建简单的融合网络
            layers = [
                imageInputLayer([size(nir,1) size(nir,2) 4], 'Name', 'input')
                
                convolution2dLayer(3, 32, 'Padding', 'same', 'Name', 'conv1')
                batchNormalizationLayer('Name', 'bn1')
                reluLayer('Name', 'relu1')
                
                convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv2')
                batchNormalizationLayer('Name', 'bn2')
                reluLayer('Name', 'relu2')
                
                convolution2dLayer(3, 32, 'Padding', 'same', 'Name', 'conv3')
                batchNormalizationLayer('Name', 'bn3')
                reluLayer('Name', 'relu3')
                
                convolution2dLayer(3, 3, 'Padding', 'same', 'Name', 'conv4')
                regressionLayer('Name', 'output')
            ];
            
            % 准备训练数据(这里使用示例数据)
            inputData = cat(3, nir, rgb);
            targetData = rgb; % 理想情况下应有真实融合图像
            
            % 训练选项
            options = trainingOptions('adam', ...
                'MaxEpochs', 20, ...
                'MiniBatchSize', 4, ...
                'Plots', 'training-progress');
            
            % 训练网络
            net = trainNetwork(inputData, targetData, layers, options);
            
            % 使用网络进行融合
            fusedImage = predict(net, inputData);
            
        otherwise
            error('未知融合方法: %s', method);
    end
    
    % 确保输出在[0,1]范围内
    fusedImage = min(max(fusedImage, 0), 1);
end

%% 辅助函数:拉普拉斯金字塔
function pyr = laplacianPyramid(img, levels)
    pyr = cell(1, levels);
    current = img;
    for i = 1:levels-1
        [pyr{i}, current] = doPyramidLevel(current);
    end
    pyr{levels} = current; % 最顶层的低频部分
end

function [high, low] = doPyramidLevel(img)
    % 高斯模糊和下采样
    low = imfilter(img, fspecial('gaussian', 5, 1), 'replicate');
    low = imresize(low, 0.5, 'bilinear');
    
    % 上采样并重建高频分量
    up = imresize(low, size(img), 'bilinear');
    high = img - up;
end

function img = reconstructPyramid(pyr)
    img = pyr{end};
    for i = length(pyr)-1:-1:1
        up = imresize(img, size(pyr{i}), 'bilinear');
        img = pyr{i} + up;
    end
end

七种融合方法详解

1. 加权平均法

  • 原理:对NIR和RGB的平均亮度进行加权平均
  • 优点:计算简单,速度快
  • 缺点:对比度降低,细节保留不足
  • 适用:实时处理系统

2. IHS变换融合

  • 原理
    1. 将RGB图像转换到HSV色彩空间
    2. 用NIR图像替换亮度(V)通道
    3. 转换回RGB空间
  • 优点:保持色彩信息,增强细节
  • 缺点:可能引入色彩失真
  • 适用:遥感图像增强

3. 小波变换融合

  • 原理
    1. 对NIR和RGB各通道进行小波分解
    2. 低频分量取平均
    3. 高频分量取绝对值大的系数
    4. 小波重构
  • 优点:细节保留好,空间一致性高
  • 缺点:计算复杂,可能产生伪影
  • 适用:医学图像、高精度地形分析

4. PCA融合

  • 原理
    1. 将NIR和RGB通道组成数据矩阵
    2. 进行主成分分析
    3. 用第一主成分增强图像
  • 优点:最大化信息保留
  • 缺点:色彩保真度较低
  • 适用:特征提取、目标检测

5. 拉普拉斯金字塔融合

  • 原理
    1. 构建多尺度拉普拉斯金字塔
    2. 在不同尺度应用不同融合规则
    3. 重建融合图像
  • 优点:多尺度信息融合效果好
  • 缺点:计算复杂度高
  • 适用:多分辨率分析、图像增强

6. 导向滤波融合

  • 原理
    1. 使用NIR图像作为引导图像
    2. 对RGB各通道应用导向滤波
    3. 保持边缘同时传输NIR细节
  • 优点:边缘保持性好,色彩自然
  • 缺点:参数敏感
  • 适用:图像去雾、增强现实

7. 深度学习融合

  • 原理
    1. 构建端到端的卷积神经网络
    2. 学习NIR和RGB的最优融合方式
    3. 自动生成融合结果
  • 优点:自适应性强,效果最好
  • 缺点:需要训练数据和计算资源
  • 适用:高质量图像融合、专业应用
% 加载图像
nir = 'nir_image.jpg';
rgb = 'visible_image.jpg';

% 创建融合结果比较图
methods = {'weighted_average', 'ihs', 'wavelet', 'pca', ...
           'laplacian', 'guided_filter', 'deep_learning'};
titles = {'加权平均', 'IHS变换', '小波变换', 'PCA融合', ...
          '拉普拉斯金字塔', '导向滤波', '深度学习'};

figure('Position', [100, 100, 1400, 1000]);
subplot(3, 3, 1); imshow(imread(nir)); title('近红外图像');
subplot(3, 3, 2); imshow(imread(rgb)); title('可见光图像');

for i = 1:7
    % 融合图像
    tic;
    fused = fuseNIR_RGB(nir, rgb, methods{i});
    time = toc;
    
    % 显示结果
    subplot(3, 3, i+2);
    imshow(fused);
    title(sprintf('%s (%.2fs)', titles{i}, time));
    
    % 保存结果
    imwrite(fused, sprintf('fused_%s.jpg', methods{i}));
end

% 评估融合质量
fprintf('\n融合质量评估:\n');
fprintf('%-20s %-10s %-10s %-10s %-10s\n', '方法', 'PSNR', 'SSIM', 'EN', 'SF');
for i = 1:7
    fused = imread(sprintf('fused_%s.jpg', methods{i}));
    [psnr, ssim, en, sf] = evaluateFusion(rgb, fused);
    fprintf('%-20s %-10.2f %-10.4f %-10.2f %-10.2f\n', ...
            titles{i}, psnr, ssim, en, sf);
end

%% 融合质量评估函数
function [psnr, ssim, en, sf] = evaluateFusion(refPath, fused)
    ref = im2double(imread(refPath));
    fused = im2double(fused);
    
    % PSNR
    mse = mean((ref(:) - fused(:)).^2);
    psnr = 10 * log10(1 / mse);
    
    % SSIM
    ssim = ssim_index(ref, fused);
    
    % 信息熵 (EN)
    grayFused = rgb2gray(fused);
    en = entropy(grayFused);
    
    % 空间频率 (SF)
    [rows, cols] = size(grayFused);
    rf = sqrt(sum(sum(diff(grayFused,1,1).^2)) / (rows*(cols-1));
    cf = sqrt(sum(sum(diff(grayFused,1,2).^2)) / ((rows-1)*cols);
    sf = sqrt(rf^2 + cf^2);
end

参考代码 多种方法融合近红外与可见光图像 www.youwenfan.com/contentcnl/83473.html

融合方法选择指南

应用场景 推荐方法 理由
实时监控 加权平均或IHS 计算速度快
遥感图像处理 IHS或小波变换 保持空间细节和色彩
医学成像 小波变换或拉普拉斯金字塔 多尺度细节保留
低光照增强 导向滤波 边缘保持,自然色彩
目标检测 PCA融合 特征增强
高质量图像生成 深度学习 自适应最优融合
资源受限环境 加权平均 最低计算复杂度

性能优化建议

  1. GPU加速

    % 将数据转移到GPU
    if gpuDeviceCount > 0
        nir = gpuArray(nir);
        rgb = gpuArray(rgb);
    end
    
  2. 并行计算

    % 对RGB通道并行处理
    parfor c = 1:3
        channelResult = processChannel(rgb(:,:,c), nir);
        fused(:,:,c) = channelResult;
    end
    
  3. 多尺度加速

    % 使用图像金字塔加速处理
    smallNIR = impyramid(nir, 'reduce');
    smallRGB = impyramid(rgb, 'reduce');
    fusedSmall = fuseMethod(smallNIR, smallRGB);
    fused = impyramid(fusedSmall, 'expand');
    
  4. 自适应融合

    % 根据局部特征调整融合策略
    edgeMap = edge(nir, 'canny');
    weightMap = imgaussfilt(double(edgeMap), 2);
    fused = weightMap.*fusionMethod1 + (1-weightMap).*fusionMethod2;
    

这些方法为近红外与可见光图像融合提供了全面的解决方案,可根据具体应用场景和性能要求选择最合适的方法。

posted @ 2025-11-10 16:09  修BUG狂人  阅读(23)  评论(0)    收藏  举报