☰
平面/矢量图水印残留调查实录:gemini-watermark-remover Issue 103 与 fail-closed 安全策略
2026/10/12 1:54:58 网站建设 项目流程

【免费下载链接】gemini-watermark-remover

A high-performance, 100% client-side tool for removing Gemini AI image & video watermarks. Built with pure JavaScript using mathematically precise Reverse Alpha Blending. / 基于 JavaScript 的纯浏览器端 Gemini AI 图像和视频无损去水印工具,使用数学精确的反向 Alpha 混合算法

项目地址:https://gitcode.com/gh_mirrors/ge/gemini-watermark-remover
点击查看免费下载

导读:本文完整复盘 gemini-watermark-remover 在 Issue #103 平面/矢量图样本上的调查过程与结论——该样本并非水印定位失败,而是去水印后的可见残留无法消除且损伤评估判定为不安全,最终落地为 fail-closed(拒绝输出)安全策略。读者将掌握visible-residual-unsafe-damage门控在生产流水线中的实现原理、单图视觉修补的"不可观测信息"根本障碍,以及vector-repair-fixture-pack这套可重复的矢量修补准入评估方法。

一、问题定位:不是检测失败,而是"残留可见 + 损伤不安全"

Issue #103 的复现样本(.artifacts/issue-103/issue-103-input.png,sha25609f83c1dcf29f6be88f7bc28dbfb8c2412dd427f038b02e14be051a8313ed6ff)在2048x2048图像中的表现,第一眼容易被误判为"水印没找到"。但调查结论明确指出:检测完全正常。

当前检测能稳定命中2048x2048图像中的96x96水印:

  • 位置:x=1760, y=1760(右下角区域)
  • 右/下边距:均为192px
  • alpha 变体:alphaVariant=20260520

这一组参数与 geminiSizeCatalog.js 中的2k-new-margintier 完全对应:

'2k-new-margin': Object.freeze({ logoSize: 96, marginRight: 192, marginBottom: 192, alphaVariant: '20260520' })

同时,96px / 192px边距水印对应的内嵌 alpha map 也真实存在于 embeddedAlphaMaps.js 的96-20260520键中。

真正的问题出现在去水印之后。修复前的 CLI 处理结果完整记录了失败形态:

字段修复前值含义
appliedtrue流水线输出了一张"处理过"的图
sourcestandard+located-aggressive检测来源为常规定位 + 激进策略
position{ x:1760, y:1760, width:96, height:96 }检测位置正确
config{ logoSize:96, marginRight:192, marginBottom:192, alphaVariant:"20260520" }采用新边距 alpha 变体
residualVisibility.visibletrue处理后残留仍可见
visibleGradientResidualtrue梯度残留超阈值
visibleSpatialResidualtrue空间残留超阈值
damage.safefalse损伤评估不安全
damage.reasontexture损伤原因为纹理破坏

这里的visible与damage并非主观判断,而是有明确数值门限的量化评估:

  • 残留可见性由 restorationMetrics.js 中的常量决定:空间残留阈值RESIDUAL_VISIBILITY_SPATIAL_THRESHOLD = 0.18、梯度残留阈值RESIDUAL_VISIBILITY_GRADIENT_THRESHOLD = 0.22、正晕光阈值RESIDUAL_VISIBILITY_POSITIVE_HALO_LUM_THRESHOLD = 6;任一维度超过即visible=true。
  • 损伤评估来自 watermarkScoring.js 的scoreDamage:hard-reject、近黑像素增量 > 0.05、纹理惩罚 > 0.25、新增裁切比例 > 0.03 任一命中即产生 reason;safe = reasons.length === 0。该样本命中了texture。

也就是说:水印找对了、alpha map 用对了,但反向 Alpha 混合之后,水印区域仍然残留明显鬼影,且处理本身引入了不可接受的纹理损伤。

二、已落地的生产修复:fail-closed 门控与visible-residual-unsafe-damage

针对 #103,生产路径没有选择"继续硬解",而是落地了一个 fail-closed(故障时拒绝输出)策略:当新边距 alpha 变体候选在处理后仍有可见残留、且损伤评估不安全时,流水线直接返回applied=false与skipReason=visible-residual-unsafe-damage,避免输出一张带明显鬼影或新增损伤的图片。

修复后的 CLI 处理结果为:

  • applied=false
  • skipReason=visible-residual-unsafe-damage
  • 同时完整保留检测位置、配置、分数、残留可见性与 decision path,供 UI/CLI/后续调试展示原因——也就是说,"拒绝"不等于"丢信息",只是不输出处理图。

2.1 门控判定条件(源码级)

门控判定集中在 candidateEvaluation.js 的shouldFailClosedForVisibleResidualUnsafeDamage:

export function shouldFailClosedForVisibleResidualUnsafeDamage({ selectedTrial = null, residualVisibility = null } = {}) { return isNewMarginAlphaVariantTrial(selectedTrial) && residualVisibility?.visible === true && selectedTrial?.damage?.safe === false; }

三个条件缺一不可:

  1. 是"新边距 alpha 变体"候选:logoSize === 96 && marginRight === 192 && marginBottom === 192 && alphaVariant === '20260520'(见同文件isNewMarginAlphaVariantTrial);
  2. 残留可见:residualVisibility.visible === true(由assessCalibratedWatermarkResidualVisibility计算,见 restorationMetrics.js);
  3. 损伤不安全:selectedTrial.damage.safe === false。

2.2 在流水线中的接入位置

finalization 阶段(createAcceptedPipelineFinalResult)先计算校准后的残留可见性,再依次检查两道 fail-closed 门:

if (allowFailClosed && shouldFailClosedForVisibleResidualUnsafeDamage({ selectedTrial: resultContext.selectedTrial, residualVisibility: safetyResidualVisibility })) { return createFailClosedPipelineResultFromState({ ... }); } if (allowFailClosed && shouldFailClosedForUnsafeWeakShiftedCandidate({ ... })) { // reason: 'unsafe-weak-shifted-candidate' }

两道门都通过后才走createAcceptedPipelineResultFromState正常输出。这保证了 #103 这类"残留可见 + 损伤不安全"的候选永远不会带着问题结果进入生产输出。

2.3 返回结果的结构设计

fail-closed 结果的构造由 pipelineResult.js 的createFailClosedPipelineResultFromState负责,其关键设计是:

  • imageData直接返回originalImageData——即原图,而不是带鬼影的处理图;
  • meta由 pipelineMeta.js 的createFailClosedWatermarkMeta生成,reason默认'visible-residual-unsafe-damage'、evidenceClass默认'unsafe-visible-residual';
  • decision path 记录blockedGate: reason,UI/CLI 可以据此向用户解释"检测到水印,但当前样本属于不安全残留,已保留原图"。

相关行为有测试兜底,见 pipelineFinalization.test.js 与 pipelineResult.test.js:均断言meta.skipReason === 'visible-residual-unsafe-damage'且blockedGate一致。

三、调查证据一:参数扫描未找到安全候选

在确定 fail-closed 之前,调查团队先做了系统性的参数扫描,相关产物包括:

  • .artifacts/issue-103/alpha-profile-small-sweep.json(alpha gain / 局部 profile 扫描)
  • .artifacts/issue-103/localization-small-sweep.json(轻微位移/缩放扫描)
  • .artifacts/issue-103/logo-value-sweep.json(logo value 扫描)
  • .artifacts/issue-103/channel-logo-sweep.json(RGB 分通道 logo value 扫描)

结论非常直接:扫描 alpha gain、局部 profile、轻微位移/缩放、logo value 与 RGB logo value 后,没有找到visible=false且安全的候选。最佳候选仍保留明显残留,只是在不同策略下把残留从亮边、暗边或局部纹理之间转移。这说明问题不在"参数没调好"。

四、调查证据二:合成模型检查——sRGB 正向叠加拟合显著优于 linear RGB

一个常见假设是"残留是因为把 linear RGB 合成当成 sRGB 处理",但该样本的合成模型检查(.artifacts/issue-103/compositing-model-fit.json)推翻了它:

  • sRGB 正向叠加拟合的 RMSE 约2.9393;
  • linear RGB 拟合的 RMSE 约48.6116。

差距超过一个数量级。也就是说,当前水印更接近sRGB alpha 模型下的背景重建问题,而不是线性合成假设导致的失败。这为后续调查指明了方向:焦点应放在"背景信息是否可观测/可重建"上。

五、调查证据三:视觉修补实验全部残留可见

第二阶段调查尝试了多种视觉修补方案,产物包括:

  • .artifacts/issue-103/flat-nearest-repair-report.json(平面最近邻填充)
  • .artifacts/issue-103/palette-repair-report.json(调色板修补)
  • .artifacts/issue-103/model-fit-palette-repair-report.json(模型拟合 + 调色板修补)
  • .artifacts/issue-103/model-fit-threshold-sweep.json(阈值扫描)
  • .artifacts/issue-103/inverse-palette-snap-report.json(反解 + 调色板 snap)
  • .artifacts/issue-103/palette-mrf-repair-report.json(调色板 + MRF 平滑)

结论:

  • inverse-palette-snap是单样本上指标最好的简单修补,但最佳结果仍为visible=true:severity=21.40704、gradientResidual=0.2578、spatialResidual=0.26759。对照第一节的阈值即可看出,0.2578 > 0.22与0.26759 > 0.18,梯度与空间残留双双超标。
  • MRF/区域平滑可以进一步压低梯度残留,但代价是增加空间残留与区域化错误(块状伪影),不适合直接上线。
  • 因此:palette snap、局部区域平滑、MRF 类视觉修补不应直接放进生产路径——它们只是把残留从一种形态换成另一种形态,并会在硬边界、细线、局部图形上引入错误重建。

六、合成 hard/vector 基准:不可观测信息是根本障碍

为了把"单样本现象"升级为"可重复的机制结论",调查构造了带 ground truth 的合成平面/矢量图基准(.artifacts/issue-103/synthetic-vector-benchmark/benchmark.json与comparison-sheet.png),故意制造 alpha gain 偏差。结果:

  • 大块纯色背景中,palette snap 有时能接近真值——因为外圈颜色足以证明水印区域的底色;
  • 局部形状只出现在水印区域内部时,即便使用 oracle alpha gain(已知真值增益),palette snap 也无法恢复隐藏形状;
  • nested-shapescase 中 palette snap 的 RMSE 约15.46,明显差于简单反解。

这证明了一个核心机制结论:单图 palette/区域重建存在不可观测信息——如果被水印遮住的颜色或形状没有在外圈出现,算法无法可靠知道真实底色,任何修补都是在"猜",而"猜错"就会在隐藏局部形状、硬边界和细线处重建错误内容。

七、vector-repair-fixture-pack:把风险变成可重复的准入门槛

基于上述结论,新增的vector-repair-fixture-pack(脚本 create-issue103-vector-repair-fixture-pack.js)把"不可观测信息"风险转化为一套带 ground truth 的可重复准入测试,共 5 个用例:

用例 ID期望含义
large-blocks-recoverablerepairable外圈存在大块连通颜色,理论上属于可修复样例
nested-shapes-protectedprotect水印区域内存在外圈不可观测的局部圆形、竖条与色块,必须保护
mixed-safe-component-protectedprotect同一 ROI 内同时存在可由外圈证明的大块连通区域,以及必须保护的内部孤立组件
thin-stripes-protectedprotect细线/条纹不应被修补算法压平成调色板块
diagonal-edge-protectedprotect硬边界穿越水印区域时不应引入边缘错位

每个用例都以PALETTE(7 色板)绘制 320x320 场景,用96-20260520alpha map 与trueGain=0.85施加水印,再对比truth / watermarked / inverse / palette-snap-repair / gated-palette-repair五个面板(见脚本中的COLUMNS)。

7.1 naive palette-snap-repair 的结果

未加门控的朴素palette-snap-repair在 fixture pack 上的汇总(summarizeVectorRepairFixtureResults,见 scripts/create-issue103-vector-repair-fixture-pack.js):

  • productionReady=false
  • repairable-improved=1
  • protected-regression=1
  • protected-not-worse=3
  • blockers:protected-regression

分类规则(classifyVectorRepairOutcome)本身就体现了"保护优先":repairable用例要求repair.rmse <= inverse.rmse * 0.4且maxError <= inverse.maxError才算repairable-improved;protect用例只要repair.rmse > inverse.rmse * 1.25或maxError > inverse.maxError + 24即判为protected-regression(生产阻断)。

7.2 gated-palette-repair:连通组件判别的研究原型

新增的gated-palette-repair研究原型不搞"全量调色板覆盖",而是从普通反解图出发,只对满足安全条件的连通组件局部采用 palette repair:

  1. createSceneLabelMap:按 alpha 投影后的颜色距离把水印区域像素贴到外圈调色板标签;
  2. analyzeVectorSceneSafety:四邻域 BFS 提取连通组件,计算每个组件的area、fillRatio(面积/包围盒面积比)、touchesBoundary(是否触碰 ROI 边界);
  3. isSafeVectorRepairComponent:组件必须面积足够、与边界连通、且近似矩形(默认minArea=256、minFillRatio=0.84、requireBoundary=true,见normalizeGateOptions);
  4. 复杂组件(内部孤立、过小、非矩形)回退到普通反解,不做任何替换。

该原型在 fixture pack 上的结果为:

  • productionReady=true
  • repairable-improved=1
  • protected-not-worse=4
  • blockers:none

这说明下一阶段的 gated vector repair 有一个可继续验证的方向:在large-blocks-recoverable上相对反解有显著收益,在mixed-safe-component-protected上能局部采用安全组件,并且在nested-shapes-protected等不可观测局部结构上不能比普通反解更差。对应测试见 issue103VectorRepairFixturePack.test.js。

八、真实 #103 样本的组件级复核与阈值 sweep

fixture 通过不等于真实样本通过,调查进一步用真实 #103 样本做了组件级复核。

8.1 真实样本组件级复核:gatedAdopted=false

复跑命令:

node scripts/create-issue103-real-component-gated-review.js

产物:

  • .artifacts/issue-103/real-component-gated-vector-review/report.json
  • .artifacts/issue-103/real-component-gated-vector-review/comparison-sheet.png
  • .artifacts/issue-103/real-component-gated-vector-review/component-map-4x.png

关键结果(脚本 create-issue103-real-component-gated-review.js 默认使用position={x:1760,y:1760,width:96,height:96}、alphaKey=96-20260520、alphaGain=0.85):

  • gatedAdopted=false
  • componentCount=13
  • 所有组件的safeForRepair=false
  • rejected reasons:too-many-components、internal-component、small-component、non-rectangular-component

也就是说,当前组件级 gate 没有在真实 #103 上误采纳任何组件,但也没有改善真实输出——13 个组件全部被安全门拦下。它仍是研究原型,不能直接进入生产路径。

8.2 组件 gate 阈值 sweep:轻微放宽无收益,极度放宽有风险

复跑命令:

node scripts/create-issue103-component-gate-sweep.js

脚本 create-issue103-component-gate-sweep.js 内置 5 档默认候选(DEFAULT_CANDIDATES),sweep 结果:

候选 IDminAreaminFillRatiorequireBoundarychangedPixels
strict-a256-fill084-boundary2560.84true0
mid-a128-fill060-boundary1280.60true0
loose-a64-fill040-boundary640.40true33
loose-a64-fill040-anywhere640.40false98
very-loose-a64-fill030-anywhere640.30false2709

数据说话:从严格到"中等"放宽,实际改动像素为 0——门控根本没有采纳组件;继续放宽到loose-a64-fill040系列也只有 33~98 个像素的视觉收益;而一旦极度放宽(very-loose-a64-fill030-anywhere),采纳量暴涨到 2709 个像素,但会进入星形、弧线、纹理交界等高风险区域。因此不支持为了 #103 在生产路径放宽组件 gate。该 sweep 的可复跑性与输出结构由 issue103ComponentGateSweep.test.js 保证。

九、继续推进后的新增实验:AI 参考输出同样失败

调查最后还跑了一组"外部方案对照"实验(产物见.artifacts/issue-103/em-palette-alpha/、blend-balance/、confident-palette-repair/、allenk-reference/),结论依然悲观:

  • 分段 alpha + 调色板 EM:visible=true,最佳约severity=23.3063、spatialResidual=0.29947、gradientResidual=0.17873,会把黄绿色弧线附近重建成块状区域;
  • 原图与反解图之间的模板相关平衡:visible=true,最佳约spatialResidual=0.18016、gradientResidual=0.30617,暗鬼影仍可见;
  • 高置信调色板局部修补:只改动约 162 个像素,结构风险低,但覆盖不足,仍然visible=true;
  • allenk/GeminiWatermarkTool 参考输出(plain、server-aggressive、soft、telea、ns、ai/FDnCNN):全部visible=true,其中 AI/FDnCNN 参考的空间残留约0.35552 ~ 0.36230,比 fail-closed 前的反解残留更高。

这些结果把问题从"参数没调好"彻底推进到了**"单张图缺少可观测背景真值"**的层面:对于 hard/vector 内容,自动修补只有在被遮挡区域的颜色类别能由外圈连通区域证明时才有生产化空间;否则会在隐藏局部形状、硬边界和细线处重建错误内容。

十、处理建议与明确不建议的方向

短期

  • 保留当前 fail-closed 行为,避免生产输出明显残留或损伤;
  • 在 CLI/UI 上将visible-residual-unsafe-damage解释为"检测到水印,但当前样本属于不安全残留,已保留原图";
  • 不要为了 #103 单样本放宽安全门或上线视觉修补。

中期

  • 请求 issue reporter 提供更多同类 flat/vector 样本,至少覆盖不同背景颜色、局部形状、细线、文字/图标与不同 1K/2K/4K 尺寸;
  • 建立 hard/vector 类 fixture 集合,用 before/after crop sheet 与 ground truth/synthetic benchmark 一起评估;
  • 将.artifacts/issue-103/vector-repair-fixture-pack/report.json的gatedSummary作为 gated vector repair 的准入报告:只有当gatedSummary.productionReady=true且人工检查comparison-sheet.png无结构回归时,才考虑进入生产路径;
  • 若继续研究修补,优先做**"可证明安全的局部常量区域识别"**:只在被遮挡区域与外圈连通、且颜色类别可由外圈证明时修复;遇到孤立局部形状、硬边界穿越或覆盖率不足时仍 fail-closed;
  • 下一阶段不应从单张 #103 样本直接改生产路径;应先用更多 flat/vector 样本验证当前连通组件 gate 的假阳性/假阴性,再决定是否允许 gated vector repair 接入生产流水线。

明确不建议的方向

  • 直接降低残留可见性阈值;
  • 把 palette snap、nearest fill、MRF smoothing 作为通用后处理上线;
  • 把 allenk 的 software inpaint 或 AI/FDnCNN 清理作为该类样本的默认兜底;
  • 从单张 #103 样本泛化 96px / 192px 新边距水印的修复策略。

十一、总结:对生产流水线的启示

Issue #103 调查的价值不止于一个 bug 的结论,它沉淀了一套可复用的方法论:

  1. 量化门控优于主观判断:visible/damage.safe都由明确阈值(空间 0.18、梯度 0.22、正晕光 6,以及 texture 惩罚 0.25 等)驱动,fail-closed 判定可复现、可测试;
  2. "找不到安全解"本身也是结论:alpha/profile/位移/logo value 全参数扫描无果、sRGB 拟合优而 linear 拟合差,说明根因是背景不可观测,而非参数没调好;
  3. 合成 ground truth 基准是验证修补算法的必要门槛:vector-repair-fixture-pack的 5 个用例把"可恢复 / 必须保护"的边界显式化,任何候选修补算法都要先过productionReady这一关;
  4. 真实样本复核防止过度拟合:fixture 上通过的gated-palette-repair原型在真实 #103 上gatedAdopted=false(13 个组件全部拒绝),证明当前安全门足够保守,也证明这类算法尚未成熟到可以上线。

最终生产行为是清晰且安全的:检测到水印 → 尝试去除 → 残留可见且损伤不安全 → 返回原图并说明原因。对用户而言,这比输出一张带鬼影或损伤的图更诚实、更可用;对后续研发而言,vector-repair-fixture-pack与组件级 gate 为"可证明安全的矢量修补"留下了一条可验证的演进路径。

【免费下载链接】gemini-watermark-remover

A high-performance, 100% client-side tool for removing Gemini AI image & video watermarks. Built with pure JavaScript using mathematically precise Reverse Alpha Blending. / 基于 JavaScript 的纯浏览器端 Gemini AI 图像和视频无损去水印工具,使用数学精确的反向 Alpha 混合算法

项目地址:https://gitcode.com/gh_mirrors/ge/gemini-watermark-remover
点击查看免费下载

相关推荐

上一篇:LAV Filters终极指南:5分钟掌握Windows最强开源解码器配置
下一篇:Dell G15终极散热控制指南:开源tcc-g15完整解决方案

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询