4、深度学习基础回顾:CNN、ResNet、Transformer在ISP中的应用

各位同学,今天我们聊聊深度学习在ISP里的几个核心模型。说实话,我刚入行那会儿,ISP还全是传统算法的天下,什么3A、去噪、锐化,都是手工调参。后来深度学习一进来,整个行业都变了。我个人习惯是,不管模型多花哨,先搞懂它为什么能用在ISP里。

这一章,我们重点回顾三个架构:CNN、ResNet、Transformer。它们不是凭空冒出来的,每一步演进都解决了实际痛点。你想想看,手机拍照为什么越来越强?背后就是这些模型在默默干活。

深度学习模型在ISP中的应用演进 ISP 核心任务 CNN:局部特征提取 ResNet:深度网络优化 Transformer:全局建模 去噪 / 去马赛克 超分辨率 / HDR RAW域增强 / 色彩重建 关键洞察 • CNN 擅长局部纹理,适合去噪、去马赛克等像素级任务 • ResNet 解决梯度消失,让 ISP 网络可以堆到 100+ 层 • Transformer 捕捉全局依赖,在色彩重建、HDR 合成中表现惊艳 • 三者融合(CNN + Transformer)是当前 ISP 算法的主流方向

4.1 CNN:ISP的基石

CNN,卷积神经网络,说白了就是用一个滑动窗口(卷积核)在图像上扫来扫去,提取局部特征。为什么它适合ISP?因为图像处理本身就是局部的——一个像素的噪点,看它周围几个像素就能判断。

我在项目中遇到过一个问题:用传统BM3D去噪,效果虽好但速度太慢。换成CNN后,一个简单的U-Net结构,速度提升了几十倍,效果还更好。嗯,这里要注意,CNN的感受野有限,如果图像有全局性的亮度不均,它可能处理不好。

CNN在ISP中的典型应用:

  • 去噪:DnCNN、FFDNet,直接学习噪声到干净图像的映射
  • 去马赛克:用CNN插值Bayer模式,比传统双线性插值好太多
  • 超分辨率:SRCNN、ESPCN,把低分辨率图变高分辨率

一个简单的CNN去噪代码片段,大家感受一下:

import torch.nn as nn

class SimpleDenoiser(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 64, 3, padding=1)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2d(64, 64, 3, padding=1)
        self.conv3 = nn.Conv2d(64, 3, 3, padding=1)
    
    def forward(self, x):
        # 残差学习:预测噪声,而不是直接预测干净图像
        noise = self.relu(self.conv1(x))
        noise = self.relu(self.conv2(noise))
        noise = self.conv3(noise)
        return x - noise  # 干净图像 = 输入 - 噪声

我的经验:CNN做ISP任务时,输入输出最好都是RAW域数据,避免sRGB域的非线性损失。我曾经在sRGB域训练去噪模型,结果RAW域测试时效果大打折扣。

4.2 ResNet:让网络深下去

CNN虽然好,但一深就出问题——梯度消失。你想想看,一个50层的网络,梯度从最后一层传到第一层,早就衰减没了。ResNet的解决方案简单粗暴:加一条“高速公路”,让梯度可以直接跳过。

这个思想在ISP里特别有用。比如做超分辨率,浅层网络学不到高频细节,深层网络又难训练。ResNet的残差连接,让我可以放心地堆到100层以上。

ResNet的核心公式:

输出 = F(x) + x

其中F(x)是卷积层学到的残差,x是输入。如果F(x)=0,网络至少不会比输入差。

我曾经在HDR合成任务里,用ResNet-50代替普通CNN。效果立竿见影——高光区域的细节保留得更完整,暗部噪点也更少。说白了,残差连接让网络可以“选择性遗忘”不重要的信息,专注于学习难的部分。

class ResidualBlock(nn.Module):
    def __init__(self, channels):
        super().__init__()
        self.conv1 = nn.Conv2d(channels, channels, 3, padding=1)
        self.bn1 = nn.BatchNorm2d(channels)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2d(channels, channels, 3, padding=1)
        self.bn2 = nn.BatchNorm2d(channels)
    
    def forward(self, x):
        residual = x
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        return self.relu(out + residual)  # 残差连接

避坑指南:ResNet不是越深越好。我在一个去噪项目里试过152层,结果过拟合了,反而比50层差。对于ISP任务,50层左右通常就够用了,再深收益递减。

4.3 Transformer:全局视野

Transformer原本是NLP的产物,但这两年杀进CV领域,势不可挡。它和CNN最大的区别是什么?CNN看局部,Transformer看全局。你想想看,一张照片的白平衡,需要参考整个画面的颜色分布,这就是全局问题。

在ISP里,Transformer特别适合做色彩重建和HDR合成。我记得有一次做RAW域的色彩校正,用CNN总是偏色,换成Transformer后,颜色一下子就准了。为什么?因为Transformer的自注意力机制,可以捕捉到远处像素之间的颜色关系。

Transformer在ISP中的优势:

  • 全局感受野:一次看到整张图,适合白平衡、色调映射
  • 动态权重:根据内容自适应调整,比CNN的固定卷积核灵活
  • 多尺度融合:可以同时处理不同分辨率的特征

不过Transformer也有缺点——计算量大。一张4K图像,直接做自注意力,显存直接爆炸。所以实际应用中,我们通常用窗口注意力(Window Attention)或者和CNN混合使用。

# 简化的自注意力机制(单头)
def self_attention(query, key, value):
    # query, key, value: [batch, seq_len, dim]
    scores = torch.matmul(query, key.transpose(-2, -1))  # 计算相似度
    scores = scores / (key.size(-1) ** 0.5)  # 缩放
    attention = torch.softmax(scores, dim=-1)  # 归一化
    output = torch.matmul(attention, value)  # 加权求和
    return output

我的建议:如果你刚开始做ISP的Transformer,别一上来就用纯Transformer。试试CNN + Transformer的混合架构,比如前面几层用CNN提取局部特征,后面用Transformer做全局建模。这样既快又好。

4.4 三者的对比与选择

说了这么多,到底什么时候用CNN,什么时候用ResNet,什么时候用Transformer?我整理了一个表格,方便大家参考:

模型 核心优势 适合的ISP任务 注意事项
CNN 局部特征提取,计算快 去噪、去马赛克、超分辨率 感受野有限,深了难训练
ResNet 解决梯度消失,支持深层网络 超分辨率、HDR合成、图像增强 注意过拟合,50层左右够用
Transformer 全局建模,动态权重 色彩重建、白平衡、HDR合成 计算量大,需要窗口优化

我个人习惯是,先分析任务需求。如果是像素级的局部处理,比如去噪,CNN就够了。如果需要全局色彩信息,比如白平衡,那就上Transformer。如果网络要很深,比如超分辨率,ResNet是首选。当然,现在的主流做法是混合使用——用CNN提取特征,用Transformer做融合,用ResNet保证深度。

总结一下:CNN是基础,ResNet是深度保障,Transformer是全局视野。三者不是互斥的,而是互补的。在ISP的AI改造中,理解它们的原理和适用场景,比盲目堆叠模型重要得多。