示例成品 看全文 ↓

修补区域有没有重复纹理

大面积Clone看单帧自然,连续播放时会显出重复节奏。

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

有人这样说「这组镜头一放就露馅,克隆块在连贯动作里来回跳,得赶紧查。」

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

已替你选好想改就点一下

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

还想怎么改可以不选

开工前请确认

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

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

我这端没收到可打开的附件,只看到文件名,不能瞎报“第几帧有问题”。
你现在二选一:

  1. 重新上传 04_012_cleaned_v03.mov + 04_012_source_plate.exr,或给可读网盘链接;
  2. 先按下面方法跑出逐帧标注,再把 mark_*.png + report.csv 发我,我帮你人工复核。

1. 先把清理镜头转成逐帧图

ffmpeg -i 04_012_cleaned_v03.mov -start_number 1 frames/%05d.png

源板如果是单张 EXR:

ffmpeg -i 04_012_source_plate.exr -vf format=rgb24 source_plate.png

如果是 EXR 序列:

ffmpeg -i 04_012_source_plate_%04d.exr -start_number 1 source_%05d.png

2. 自动查两件事

  • JUMP:时序抖动突变,即相邻帧局部运动方向/速度突然跳变。
  • CLONE_REPEAT:可疑跳动区域周围还有高相似重复块,疑似克隆纹理。

脚本保存为 check_jump_clone.py:

import os, glob, csv
import cv2
import numpy as np

FRAME_DIR = "frames"
OUT_DIR = "marks"
os.makedirs(OUT_DIR, exist_ok=True)

files = sorted(glob.glob(os.path.join(FRAME_DIR, "*.png")))
if len(files) < 2:
    raise SystemExit("没有帧,先跑 ffmpeg 转帧")

prev = cv2.imread(files[0])
prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
prev_flow = None
rows = []

for idx in range(1, len(files)):
    cur = cv2.imread(files[idx])
    if cur is None:
        continue

    gray = cv2.cvtColor(cur, cv2.COLOR_BGR2GRAY)
    h, w = gray.shape

    flow = cv2.calcOpticalFlowFarneback(
        prev_gray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0
    )

    if prev_flow is not None:
        # 帧间运动变化量:jerk
        jerk = np.linalg.norm(flow - prev_flow, axis=2)
        jerk = cv2.GaussianBlur(jerk.astype(np.float32), (5, 5), 0)

        med = float(np.median(jerk))
        thr = max(1.0, med * 2.0)  # 调小更敏感,调大更保守

        _, mask = cv2.threshold(jerk, thr, 255, cv2.THRESH_BINARY)
        mask = cv2.morphologyEx(
            mask.astype(np.uint8), cv2.MORPH_CLOSE, np.ones((5, 5), np.uint8)
        )

        cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        contours = cnts[0] if len(cnts) == 2 else cnts[1]

        for c in contours:
            x, y, bw, bh = cv2.boundingRect(c)
            if bw * bh < 60 or bw < 5 or bh < 5:
                continue

            score = float(np.mean(jerk[y:y+bh, x:x+bw]))
            rows.append([
                idx, os.path.basename(files[idx]),
                "JUMP", x, y, bw, bh, round(score, 2)
            ])

            cv2.rectangle(cur, (x, y), (x+bw, y+bh), (0, 0, 255), 2)
            cv2.putText(
                cur, "JUMP", (x, y-5),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1
            )

            # 只在 JUMP 区域周边查重复纹理块
            pad = 12
            bx0, by0 = max(0, x-pad), max(0, y-pad)
            bx1, by1 = min(w, x+bw+pad), min(h, y+bh+pad)
            rw, rh = bx1-bx0, by1-by0

            if rw < 16 or rh < 16:
                continue

            templ = gray[by0:by1, bx0:bx1]
            res = cv2.matchTemplate(gray, templ, cv2.TM_CCOEFF_NORMED)
            _, max_val, _, max_loc = cv2.minMaxLoc(res)
            cx, cy = max_loc

            # 排除自己
            if bx0 <= cx <= bx0 + rw and by0 <= cy <= by0 + rh:
                continue

            if max_val > 0.95:  # 调高更严格,调低更敏感
                rows.append([
                    idx, os.path.basename(files[idx]),
                    "CLONE_REPEAT", cx, cy, rw, rh, round(float(max_val), 3)
                ])
                cv2.rectangle(cur, (cx, cy), (cx+rw, cy+rh), (0, 255, 255), 2)
                cv2.putText(
                    cur, "CLONE", (cx, cy-5),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1
                )

    cv2.imwrite(os.path.join(OUT_DIR, f"mark_{idx:05d}.png

别人还这样问

同类还能办

全部 ›
把提示词失败日志转成归因表格免费看示例 ›死循环卡死怎么排查免费看示例 ›屎山代码怎么安全重构免费看示例 ›把报错日志转成排查步骤免费看示例 ›怎么给老代码补单元测试免费看示例 ›核对时钟配置是不是一致免费看示例 ›

同样出写代码做网站的

首页