实时视频超分辨率:端侧 SR 模型从训练到上屏

本文拿视频超分练手:把 720p 的旧视频、或者低清视频流,在手机上实时放大到 1080p 甚至 4K。端侧超分的难点不在效果,在「一帧只有 16ms 预算」。

1、你遇到的场景

“直播流的源只有 480p,在大屏上糊成一团。想上超分,云端方案要上传每帧画面,流量和隐私都扛不住。找个现成模型,手机上一跑 300ms/帧,直接卡成 PPT……”

端侧超分的核心矛盾:

  1. 算力 vs 画质 — 大模型效果好但慢,小模型快但糊
  2. 实时预算 — 30fps 一帧 33ms,留给超分的只剩 10ms 左右
  3. 模型体积 — 好的超分模型动辄几十 MB,App 体积压力大

2、端侧超分的两条路线

路线代表参数量帧耗时(iPhone15)效果适用
轻量 CNNESPCN / FSRCNN5~50K3~8ms中等实时视频
重 SRSRGAN / ESRGAN1M+100ms+好离线照片
高效重 SRReal-ESRGAN-small300K15~30ms较好半实时

核心洞察: 视频超分和照片超分是两个物种。视频能利用时域连续性(前后帧信息),且对单帧瑕疵容忍度高——所以用轻量 CNN + 帧间复用,比堆大模型更划算。

端侧视频超分管线:

低清帧(480p) → 预处理(YUV→RGB,归一化) → SR 模型(×2) → 后处理 → 1080p 帧
                    ↑                                      ↓
               复用上一帧光流/残差                       送编码器

3、选一个能实时跑的 SR 模型

# 训练侧:用 ESPCN 做基线(×2 超分,亚像素卷积,轻量)
# super_resolution.py(Claude Code 生成)
import torch
import torch.nn as nn

class ESPCN(nn.Module):
    """亚像素卷积超分:先卷积升通道,再 pixel shuffle 重排上采样"""
    def __init__(self, scale=2):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 64, 5, padding=2)
        self.conv2 = nn.Conv2d(64, 32, 3, padding=1)
        self.conv3 = nn.Conv2d(32, 3 * scale * scale, 3, padding=1)
        self.shuffle = nn.PixelShuffle(scale)

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = torch.relu(self.conv2(x))
        return self.shuffle(self.conv3(x))

# 参数量才 20K,导出后 INT8 量化只有 ~100KB,天然适合端侧

导出 + 量化:

# ONNX → CoreML(iOS,FP16 走 ANE)
python -c "
import coremltools as ct
m = ct.convert('espc.onnx', minimum_deployment_target=ct.target.iOS16,
               compute_precision=ct.precision.FLOAT16)
m.save('espc.mlpackage')
"

# ONNX → TFLite(Android,INT8)
# 量化后 20K 参数的模型几乎无损

4、端侧推理:复用引擎,逐帧喂入

关键优化:不要每帧新建 interpreter,只换输入 buffer。

// SuperResolution.swift (iOS)
// 视频超分:复用 CoreML 引擎,逐帧上采样

final class SuperResolver {
    private let engine: MLInferenceEngine   // 上篇的统一抽象
    private let scale: Int

    init(scale: Int = 2) throws {
        self.scale = scale
        self.engine = try CoreMLEngine(bundle: "espc")
    }

    /// 输入低清帧 RGBA,输出高清帧 RGBA
    func upscale(_ lowRes: CVPixelBuffer) -> CVPixelBuffer? {
        // 1. CVPixelBuffer → MLTensor(归一化 0~1,NHWC)
        let tensor = Self.tensorFrom(pixelBuffer: lowRes)
        // 2. 推理(同步,16ms 预算内)
        guard let out = try? engine.predict(tensor) else { return nil }
        // 3. MLTensor → CVPixelBuffer(反归一化,写回 8bit)
        return Self.pixelBufferFrom(tensor: out, scale: scale)
    }
}
// SuperResolver.kt (Android)
// 视频超分:SurfaceTexture 回调里逐帧处理

class SuperResolver(private val engine: MLInferenceEngine) {

    // onFrame 来自 Camera2/MediaCodec 回调,跑在 GL 或专用线程
    fun onFrame(lowRes: ByteBuffer, out: ByteBuffer): Boolean {
        val input = MLTensor(intArrayOf(1, H, W, 3), lowRes)
        val result = engine.predict(input)
        result.data.rewind()
        result.data.get(out)   // 拷贝到预分配的输出 buffer
        return true
    }

    companion object {
        private const val W = 480
        private const val H = 270
    }
}

5、帧间复用:用上一帧省算力

视频相邻帧高度相似。高级玩法:只对「变化区域」做超分,静止区域复用上一帧结果。

帧 t-1: ┌──────────────┐
        │   静止区域    │ ← 复用 t-1 的超分结果
        │   ┌────┐      │
        │   │变化│ ← 只对这格跑 SR
        │   └────┘      │
        └──────────────┘
# 简单版:帧差检测(Claude Code 生成)
# 低清帧之间做像素差,超过阈值的块才进 SR
def change_mask(prev_gray, cur_gray, block=16, thr=8.0):
    import numpy as np
    H, W = prev_gray.shape
    mask = np.zeros((H // block, W // block), dtype=np.bool_)
    for by in range(H // block):
        for bx in range(W // block):
            b0 = prev_gray[by*block:(by+1)*block, bx*block:(bx+1)*block]
            b1 = cur_gray[by*block:(by+1)*block, bx*block:(bx+1)*block]
            if np.abs(b0.astype(float) - b1.astype(float)).mean() > thr:
                mask[by, bx] = True
    return mask   # True = 该块需要重新超分

6、踩坑记录

#问题现象根因修复
1越跑越卡前几秒流畅后掉帧每帧 new Interpreter 内存抖动复用 interpreter + 预分配 buffer
2颜色发白超分后画面灰蒙蒙归一化/反归一化范围不对训练与推理用同一套 [0,1] 约定
3首帧黑屏第一帧无输出模型未 warmup启动时跑一次空输入 warmup
4绿边/伪影物体边缘有颜色溢出INT8 量化损失 + 无校准校准集量化,边缘任务用 FP16
5ANE 不工作一直 CPU 跑动态 shape固定输入 shape 到 mlpackage
6放大 4x 崩2x 正常 4x 崩4x 计算量平方级增长4x 拆成两次 2x 级联

学习和提升音视频开发技术,欢迎你加入我们的知识星球

实时视频超分辨率:端侧 SR 模型从训练到上屏

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

赞 (0)

相关推荐