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

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

我将介绍七种不同的近红外(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. 加权平均法

2. IHS变换融合

3. 小波变换融合

4. PCA融合

5. 拉普拉斯金字塔融合

6. 导向滤波融合

7. 深度学习融合

 

% 加载图像
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

参考代码 多种方法融合近红外与可见光图像

融合方法选择指南

应用场景 推荐方法 理由
实时监控 加权平均或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;
    

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

专注于matlab/simulink,电子电路,编程