news 2026/9/30 9:17:43

jevgrep 截图对比评审技能实战:用“更不错误“原则与视觉遥测指标客观裁决截图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
jevgrep 截图对比评审技能实战:用“更不错误“原则与视觉遥测指标客观裁决截图

【免费下载链接】jevgrep

Find code by asking what it does. A CLI for coding agents that uses Jev to discover relevant files and source context.

项目地址:https://gitcode.com/gh_mirrors/je/jevgrep
点击查看免费下载

本文深入解读 jevgrep 仓库中.agents/skills/compare-screenshots/SKILL.md所定义的截图对比评审技能。它解决的是视觉开发中最棘手的判断问题:当候选渲染图与基准图存在差异时,如何客观判断"哪一边更接近正确",而不是机械地要求匹配基准。读完本文,你将掌握一套完整的六步评审工作流、双图对比与单图自检的全部指标语义、固定的距离分数公式,以及配套脚本visual-parity-diff.mjs的真实用法与自检方式,可直接用于 UI、游戏画面、文档渲染、图表等任何生成资产的接受/拒绝决策。

核心原则:判断"哪张图更不错误",而非"是否匹配基准"

该技能的第一条纪律就是反转直觉:比较的目标是"哪张图更不错误"(less wrong),而不是"候选图是否与基准一致"。

基准(baseline)只是更早的一次尝试,它同样可能是错的——可能相机意图不对、内容缺失、光照错误或裁剪有问题。因此:

  • 两张图都只是候选者(candidates),统一用你自行建立的目标(target)来衡量;
  • 指标的作用是定位两张图在哪些地方不同(locate divergence),它们永远不会替你裁决谁是对的;
  • 距离为 0 不代表成功(可能是两张图错得一样),距离很大也不代表失败(更丰富的场景、更清晰的模型、更实的标签、真正的深度、更好的光照都会合法地拉大距离)。

这一原则贯穿整个技能:所有指标、公式、脚本产物都围绕"定位差异"设计,而把"裁决"留给第 4 步基于目标的逐项判断。

六步评审工作流

技能的完整工作流如下,每一步都不可跳过:

  1. 从第一性原理建立目标(Establish the target from first principles)。在查看任何距离指标之前,先决定这张图应该呈现什么:视觉需求、设计意图、真实世界里物体长什么样,以及拥有该画面话语权的领域技能。这——不是基准——才是 ground truth。用一两句具体的话写下来(例如"低角度的太阳应向东投下长影;树木应填满树冠;标签在这个缩放级别下保持可读")。
    • 如果正确答案不明确——存在互相竞争的合理解读、品味或产品意图之争、只有负责人能拍板的权衡——停下来问用户正确答案应该是什么,并把对比结果展示给他们。不要为了省事而悄悄默认基准,那会把基准犯下的错误固化下来。
  2. 确认可比性(Confirm comparability),确保你看到的差异是真实的而非采集伪影:相同的视口(viewport)、DPR、路由/页面、冻结的时间/帧、相机意图、UI 状态、数据、字体/资源。不可比则修正采集设置,或只对比差异无害的裁剪/局部特征。
  3. 生成定位差异的产物(Generate artifacts to locate divergence),规模与问题匹配:并排图(side-by-side)、关键特征裁剪/放大(crops/zooms)、灰度图、绝对灰度热力图、pixelmatch 差异图、每张图的 Sobel 边缘图、边缘差异热力图,以及 JSON 指标。
  4. 逐项对照目标裁决每个差异(Judge each divergence against the target)。对每一处不同,用平实的语言说出那里实际有什么——内容缺失、相机错误、层级混乱、对比度弱、深度错误、文字重叠、布局偏移、边缘被裁、意外模糊、风格不匹配——并判断哪一边更接近正确。答案可以是:候选对、基准对、两者都错、或真正的难分伯仲。
  5. 对争议或高风险结论获取中立第二意见(Get a neutral second opinion):让一个全新的子代理(subagent)只拿到两张图和中性标签进行独立判断,配置见 references/subagent-visual-review.md。
  6. 以一个裁决收尾(Conclude with one verdict):候选更不错误(接受,并在存在基准时重新 bless 基准)、基准更不错误(拒绝)、两者都错(需要再来一轮——指出还差什么)、或结论不清(询问用户)。绝不因为分数更低就接受、或因为分数更高就拒绝。绝不隐藏内容、模糊细节、裁掉差异、或让采集变得不真实来推动某个数字。

双图对比指标:为"问题"挑选"度量"

在完整视觉对比中,技能建议报告以下指标(全部可追溯到脚本visual-parity-diff.mjs的实际输出字段):

指标含义说明
mae灰度平均绝对差(0..255)越低越接近
rmse灰度均方根误差越低越接近
diffRatio16/32/64灰度差超过 16/32/64 的像素占比三个阈值下越界像素的比例
pixelmatchRatio灰度图上 pixelmatch 的不匹配像素占比由 pixelmatch 库在阈值 0.08、含抗锯齿(includeAA: true)下计算
edgeEnergyCurrent/edgeEnergyCandidate两侧的平均 Sobel 边缘强度判断画面结构丰富度
edgeEnergyRatio候选/当前的边缘能量比远低于 1 通常意味着几何、道具、标签或地形缺失;远高于 1 通常意味着噪点或错误细节
edgeDiffRatio32Sobel 边缘差异超过 32 的像素占比结构差异的量化
avgLuminanceCurrent/Candidate/Delta平均亮度及差值当渲染明显偏暗/偏亮、即使整体距离分数改善时使用

针对场景还提供内容代理指标(content proxies):black/void 占比(blackRatio)、类地形占比(terrainLikeRatio)、水类占比、队伍颜色占比、标签/文字掩码占比。脚本中的isTerrainLike实现为:g > 72 && r > 62 && b > 38 && r > b * 0.92 && g > b * 0.92。

对于 UI/文档/布局类评审,还应使用裁剪边界(crop bounds)、文字/前景掩码覆盖率、对比度检查、边缘裁切、元素位置与前后尺寸——这些在击败全局像素距离时优于全局像素指标。

单图指标:没有对照时,如何判断一张截图是否值得

每一对指标都在"图 vs 图",没有任何一个能回答"这张截图值不值得"——当没有东西可比时;而且对分数是对称的,巨大的距离永远不说明哪一边是空帧。以下绝对数值可以,它们在单张 PNG 的粗网格上计算:

  • colorEntropyBits低于约 3.0,或dominantColorShare超过约 0.6:一种颜色统治了整帧——稀疏场景、未点亮场景、或主体从未被画出来。
  • edgeDensity低于约 0.04:几乎没有任何形状——空取景、图元主导的场景、或主体在裁剪框之外。
  • luminanceContrast低于约 60:雾、黑暗或薄雾把整帧压进同一个色带。
  • transparentShare在应当不透明的截图上大于 0:截图本身错了。透明像素保留着遗留的 RGB,所以一帧不可见的画面在被合成前可能看起来很丰富——场景指标先做合成再测量,并如实报出不可见占比,而不是让你去推断。成对指标仍读取存储的 RGB,所以这个字段是透明度被如实讲出来的唯一位置。

从源码看,computeSceneMetrics按约 160×90 的粗网格采样(stepX = max(1, floor(width/160)),stepY = max(1, floor(height/90))),每通道取 4 bit 分桶(key = r>>4, g>>4, b>>4),这样梯度与抖动不会误读为"精心创作的多彩",成本也远低于成对计算。

这些阈值是"怀疑"的触发器,不是门禁。刻意极简的设计、夜景、空状态页面、白板都会诚实地触发它们。用途是决定"往哪儿看",然后说出这帧画面实际在做什么——永远不要为了抬高某个数字而调整采集,这与裁掉差异是同一种失败。

距离分数:一个固定配对数字的默认公式

当需要一个固定的单对数字时,技能给出适用于结构变化默认公式:

distance = 0.35 * diffRatio32 + 0.25 * pixelmatchRatio + 0.25 * edgeDiffRatio32 + 0.15 * min(1, abs(log2(edgeEnergyRatio)))

它衡量的是与另一张图的距离,仅此而已。因为基准可能错,距离 0 不是成功、大距离也不是失败——更丰富的场景、更清晰的模型、更强的标签、真实的深度、更好的光照都会合法地抬高它。用法是:用这个分数找到图像"移动"的位置,在第 4 步裁决谁对。脚本中报告字段命名为parityDistance,报告注记明确写着"This is a distance metric, not an acceptance gate",并且输出会同时给出全帧分数和(当 UI 主导画面时)带标签的世界裁剪分数——用世界裁剪分数定位渲染器移动,保留全帧分数让 UI/相机错误继续可见。

实现细节值得一提:edgeEnergyRatioOf为两个都没有边缘的帧设了1e-6下限并返回 1——两张完全没有边缘的平坦帧不是"无限远",而是同一帧;如果直接做除法,一对相同的空渲染(正是这套指标要抓的情况)会被送到非零距离。

分数纪律

  • 每一轮迭代都引用同一对的上一次与本次距离,然后说明移动方向:朝目标、远离目标、还是诊断性噪声。
  • 缺内容类 bug 优先用边缘指标:一张平坦的俯视地图可能展现出欺骗性的中等灰度差,而边缘能量能证明树木、道路、城市轮廓或军队剪影确实不存在。
  • 当稳定 UI 主导画面而问题在场景渲染时,先分割出稳定 UI,同时保留一个带标签的全帧分数。
  • 相机错了,像素分数只是诊断性的。先修相机意图,再判断渲染。

配套脚本实战:visual-parity-diff.mjs

技能规定:对比脚本应保留在技能内部或临时工作区,不要放进产品代码——除非产品确实需要在运行时做截图对比。本仓库内提供了现成的可复用助手:

# 成对模式:需要 REFERENCE_DIR 与 CANDIDATE_DIR REFERENCE_DIR=<png文件夹> CANDIDATE_DIR=<png文件夹> OUT_DIR=<产物文件夹> node .agents/skills/compare-screenshots/scripts/visual-parity-diff.mjs # 固定配对顺序:按 a,b,c 的顺序固定报告排序 REPORT_ORDER=a,b,c # 带标签裁剪:按图像 id 键控,单位为像素或 { "unit": "ratio" } 归一化边界 CROPS_JSON=<file.json> # 单图模式:不设 REFERENCE_DIR,只测量每张截图的自身指标 CANDIDATE_DIR=<png文件夹> OUT_DIR=<产物文件夹> node .agents/skills/compare-screenshots/scripts/visual-parity-diff.mjs

行为细节(与 SKILL.md 及源码一致):

  • 有REFERENCE_DIR时执行成对差异:按文件名(.png后缀)匹配REFERENCE_DIR与CANDIDATE_DIR中的共同图片,尺寸不一致直接抛错(image sizes differ),每对生成 8 类产物:*-side-by-side.png、*-current-gray.png、*-candidate-gray.png、*-absdiff.png、*-pixelmatch.png、*-current-edges.png、*-candidate-edges.png、*-edge-diff.png,并写入visual-parity-diff.json,结果按parityDistance降序排列,报告同时标注worstPair。
  • 有CROPS_JSON时对指定裁剪区域做同样的全套分析,产物前缀为*-world-crop-*,输出独立的parityDistance与同结构指标。
  • 不设REFERENCE_DIR时只写scene-metrics.json,不含任何 diff 产物——用于孤立截图、任何人在评审前检查完整采集集、或判断大距离中哪一边才是空帧。
  • 透明像素先按 alpha 复合到 RGB 再测(r = png.data[o] * alpha),因此"不可见帧看起来丰富"的陷阱会被transparentShare直接点名。
  • 灰度用 Rec. 601 亮度权重:0.2126 * r + 0.7152 * g + 0.0722 * b;Sobel 用 3×3 邻域算子(gx = -a -2d -g + c + 2f + i等),边缘能量按像素归一。
  • 脚本从REPO_ROOT(缺省为当前工作目录或其父目录)解析web/package.json中的pngjs与pixelmatch依赖,运行前需保证这些依赖在对应仓库中可解析。

用 eval 脚本守住助手本身

visual-parity-diff.eval.mjs 是助手的自检测试:它用draw()逐像素生成正确性"由构造即已知"的夹具——空(empty-solid、empty-transparent-noise、empty-transparent-white、empty-smooth-gradient)、有内容(content-noise、content-scene)、图元主导(primitive-dominant)、半透明混合(mixed-half-transparent)、低对比度暗帧(dim-lowcontrast)、微小真实图(small-but-real)、退化图(one-pixel-wide)——然后断言:

  • 场景指标能正确区分"空"与"有内容"(colorEntropyBits < 3.0 || dominantColorShare > 0.6 || edgeDensity < 0.04判空);
  • 全透明帧报transparentShare === 1、不透明帧报 0、半透明帧接近 0.5;
  • 尺度不变性(同一场景 1x 与 2x 分辨率的edgeDensity、colorEntropyBits接近)与色调不变性(纯红/纯蓝的平坦度指标完全相等);
  • 透明黑覆在噪点上与其合成等价物(flat-black)指标完全一致;
  • 成对模式:相同对距离为 0、距离对称、两侧都带sceneMetrics以打破对称平局、仍写出 diff 产物而单图模式不写任何 diff 产物;
  • 263 张批量图的管道化 stdout 完整可解析、与落盘报告一致;
  • 失败路径响亮:缺CANDIDATE_DIR、空目录都会非零退出并打印明确错误。

运行方式:REPO_ROOT=<repo> node visual-parity-diff.eval.mjs,在修改脚本后用同一REPO_ROOT运行,任一期望集失败即非零退出并打印所有检查项。纪律是:绝不允许用放宽阈值来通过失败检查——除非先证明错的是夹具而不是代码。

中立子代理评审:防止历史偏差污染判断

当对话历史或先前的结论可能影响主代理的视觉判断时,使用 references/subagent-visual-review.md 中定义的独立评审配置:

  • 生成配置:agent_type: default、fork_context: false、把两张截图作为local_image附上、中性标签Image A/Image B或Reference/Candidate;绝不告诉子代理哪张是候选、参考、期望、已接受、已失败、更新、更旧、更好或更差。
  • 提示词要点:子代理"对同一视觉目标的两张截图做无偏视觉评审,无任何先验上下文",报告:① 是否显示相同的视口/状态/内容;② 相机/视角、布局、内容、缺失细节、标签/文字、图标、颜色、光照、深度/层次、裁切、伪影、可读性、风格上的主要可见差异;③ 对表面任务而言哪张更完整/可读,为什么;④ 关于图像是否保持预期视觉关系或需要再来一轮的简明裁决——"不要假设任一张是期望目标,只依据可见像素判断"。
  • 结果的使用:把子代理结果当作"哪张更不错误"的独立证据,不是指标或你自己检查的替代品,也不是支持基准的投票。若子代理指出相机错误、状态不匹配、内容缺失或可见伪影,先修采集/渲染质量再判断其余;当它改变或确认下一个实现目标时,把裁决引述到工作笔记中。

何时使用该技能

按技能自身的触发条件,当以下场景出现时启用:UI、游戏、文档、渲染、图表或生成资产需要客观视觉遥测、并排检查、裁剪/缩放评审,或在接受/拒绝一次视觉变更前需要一份全新的第二意见;也适用于只有一张截图、没有对照的情况——用它测量该帧是否平坦、空洞或取景糟糕,趁任何人评审之前。

本文所有指标语义、公式、阈值与运行方式均以 SKILL.md 为准,实现细节可对照 visual-parity-diff.mjs 与 visual-parity-diff.eval.mjs 两处源码验证。

【免费下载链接】jevgrep

Find code by asking what it does. A CLI for coding agents that uses Jev to discover relevant files and source context.

项目地址:https://gitcode.com/gh_mirrors/je/jevgrep
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 9:16:44

S7-200与MCGS触摸屏的电锅炉控制系统联调实战

1. 先想明白&#xff1a;电锅炉控制需求怎么拆成IO和逻辑接手电锅炉控制柜这种项目&#xff0c;最忌讳一上来就打开编程软件。我在现场吃过亏&#xff0c;程序写到一半发现水温调节的工艺要求和原来的思路完全对不上&#xff0c;回头改逻辑不仅费时间&#xff0c;还容易把报警联…

作者头像 李华
网站建设 2026/9/30 9:16:24

校园网三层架构与VLAN划分:16432信息点需求分析实战

简介&#xff1a;这份《校园网需求分析报告》面向网络工程、系统集成方向的学生与从业者&#xff0c;以常州信息职业技术学院为实例&#xff0c;系统梳理校园网从需求到架构的完整分析思路&#xff0c;适合课程设计、方案撰写或投标参考。资源包内含1个doc文档&#xff0c;压缩…

作者头像 李华
网站建设 2026/9/30 9:16:17

PHP 7.4 伪静态配置不生效怎么排查

前言伪静态&#xff08;URL rewrite&#xff0c;地址重写&#xff09;不生效&#xff0c;症状通常高度一致&#xff1a;本地开发环境因为跑的是 php -S 或者 Apache 带 .htaccess&#xff0c;/article/123 这样的地址访问得好好的&#xff1b;换到线上 nginx 之后&#xff0c;所…

作者头像 李华
网站建设 2026/9/30 9:14:43

SpringBoot+Vue日用品仓储管理系统毕设完整设计与实现解析

每个做毕设的同学心里都清楚&#xff1a;选对题目等于成功一半。日用品仓储管理系统这个方向&#xff0c;属于典型的管理信息系统类题目&#xff0c;业务逻辑清晰、技术栈主流、功能可扩展性强&#xff0c;既不会像“电商秒杀”那样把并发复杂度拉满&#xff0c;也不会像“图书…

作者头像 李华
网站建设 2026/9/30 9:14:39

113个JS特效动画合集:从Canvas粒子到页面动效的实战指南

收集JS特效动画这件事&#xff0c;我干了至少有五年。一开始只是想给自己维护的组件库配一套统一的动效选集&#xff0c;后来发现每次做活动页、官网、数据大屏、产品落地页&#xff0c;都会遇到几乎同样的诉求——需要一个“不落俗套”的入场动画、一个能跟着数据变的图表动效…

作者头像 李华