示例成品 看全文 ↓

哪些帧在闪烁或有噪点

轻微闪烁静帧看不出,却会在大屏和连续播放中非常明显。

免费看示例成品:表格 · 报告 · 代码写代码做网站 ›

有人这样说「这组镜头在大屏放的时候,噪点忽明忽暗,得赶紧查清楚是哪几帧出问题。」

能替你选的都选好了。不想动,直接点下面「交给 AI 办」,点一下就开始做;想改,就点一下要的那个。

已替你选好想改就点一下

更多选项(一般不用动)

只有你知道的不填就先空着,成品里留【待填】

还想怎么改可以不选

开工前请确认

高级选项一般不用动 · 这件事通常 1–3 分钟做好

示例成品全文按上面这组示例选项真跑出来的

先说结论:当前对话里我拿不到 seq_045.exr 的实际像素数据,所以不能直接给出“第几帧有问题”的真实结果。下面是直接可跑的脚本,跑完会生成你要的 3 个交付物:

  • Excel 明细表:seq_045_noise_audit.xlsx
  • 异常帧号 CSV:seq_045_abnormal_frames.csv
  • 给 VFX 主管看的报告:seq_045_noise_report.md

如果 seq_045.exr 不是序列而只是单个文件,脚本只能做单帧噪点评估,判断不了“忽明忽暗”。序列目录里应是一组命名类似 seq_045.0001.exr、seq_045.0002.exr 的文件。


直接可跑的脚本

把下面脚本保存为 audit_seq045.py,改好 SEQ_DIR 和 SEQ_PATTERN,运行即可。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
seq_045 噪点帧审计脚本
输出:
  - seq_045_noise_audit.xlsx      全帧明细 Excel
  - seq_045_abnormal_frames.csv   异常帧号 CSV
  - seq_045_noise_report.md       给 VFX 主管看的报告

用法:
  1) 安装依赖:pip install numpy pandas openpyxl opencv-python imageio
  2) 修改 SEQ_DIR 和 SEQ_PATTERN 为实际序列路径/命名
  3) 运行:python audit_seq045.py
"""

import os
import re
import glob
import numpy as np
import pandas as pd
import cv2

# ====== 按实际路径改这里 ======
SEQ_DIR = r"./seq_045"
SEQ_PATTERN = "seq_045*.exr"
# ===============================

EXCEL_PATH = "seq_045_noise_audit.xlsx"
CSV_PATH = "seq_045_abnormal_frames.csv"
REPORT_PATH = "seq_045_noise_report.md"

def natural_key(name):
    nums = re.findall(r"\d+", name)
    return [int(n) for n in nums]

def read_linear_rgb(path):
    """读取 EXR 为线性 RGB float32。优先 OpenCV,失败则 imageio/OpenEXR。"""
    # 方式 1:OpenCV
    try:
        arr = cv2.imread(path, cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)
        if arr is not None:
            if arr.dtype != np.float32:
                arr = arr.astype(np.float32) / 255.0
            return cv2.cvtColor(arr, cv2.COLOR_BGR2RGB).astype(np.float32)
    except Exception:
        pass

    # 方式 2:imageio
    try:
        import imageio.v3 as iio
        arr = iio.imread(path)
        if arr.ndim == 2:
            arr = np.repeat(arr[..., None], 3, axis=2)
        elif arr.shape[-1] > 3:
            arr = arr[..., :3]
        return arr.astype(np.float32)
    except Exception:
        pass

    # 方式 3:OpenEXR
    try:
        import OpenEXR
        import Imath
        exr = OpenEXR.InputFile(path)
        hdr = exr.header()
        dw = hdr["dataWindow"]
        w = dw.max.x - dw.min.x + 1
        h = dw.max.y - dw.min.y + 1
        pt = Imath.PixelType(Imath.PixelType.FLOAT)
        r = np.frombuffer(exr.channel("R", pt), dtype=np.float32).reshape(h, w)
        g = np.frombuffer(exr.channel("G", pt), dtype=np.float32).reshape(h, w)
        b = np.frombuffer(exr.channel("B", pt), dtype=np.float32).reshape(h, w)
        return np.stack([r, g, b], axis=-1).astype(np.float32)
    except Exception:
        pass

    raise IOError(f"无法读取 EXR: {path}")

def brightness(rgb):
    return 0.2126 * rgb[..., 0] + 0.7152 * rgb[..., 1] + 0.0722 * rgb[..., 2]

def robust_noise_sigma(residual):
    med = np.median(residual)
    mad = np.median(np.abs(residual - med))
    return float(1.4826 * mad)

def analyze_frame(path, prev_res):
    rgb = read_linear_rgb(path)
    y = brightness(rgb).astype(np.float32)

    # 高频残差:去掉低频结构,剩下的主要就是噪点/颗粒
    y_blur = cv2.GaussianBlur(y, (0, 0), sigmaX=1.0)
    res = y - y_blur

    noise_sigma = robust_noise_sigma(res)

    # 暗部:取最暗 5% 像素,评估暗部颗粒
    dark_cut = np.quantile(y, 0.05)
    dark_mask = y < dark_cut
    if dark_mask.sum() < 200:
        dark_noise = np.nan
    else:
        dark_res = res[dark_mask]
        dark_noise = 1.4826 * np.median(np.abs(dark_res - np.median(dark_res)))

    # 帧间残差差异:用于抓“忽明忽暗”
    if prev_res is not None and prev_res.shape == res.shape:
        diff = res - prev_res
        flicker_diff = flo

别人还这样问

同类还能办

全部 ›

同样出写代码做网站的

首页