@pilio/gemini-watermark-remover 1.0.30 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/video-app.js +1 -1
- package/package.json +2 -1
- package/src/core/adaptiveDetector.js +57 -13
- package/src/core/candidateEvaluation.js +44 -18
- package/src/core/candidateSelector.js +115 -18
- package/src/core/geminiSizeCatalog.js +0 -1
- package/src/core/imageWatermarkPipeline.js +98 -3
- package/src/core/pipelineAcceptedExecutor.js +9 -5
- package/src/core/pipelineAlphaStageSpecs.js +81 -0
- package/src/core/pipelineAlphaTraceContract.js +3 -1
- package/src/core/pipelineAlphaTrial.js +98 -15
- package/src/core/pipelineCandidateQuality.js +49 -9
- package/src/core/pipelineFinalization.js +17 -9
- package/src/core/pipelineInitialSelection.js +596 -14
- package/src/core/pipelineMeta.js +37 -11
- package/src/core/pipelineRepairStageSpecs.js +4 -0
- package/src/core/pipelineRuntime.js +23 -2
- package/src/core/previewAlphaCalibration.js +6 -3
- package/src/core/restorationMetrics.js +214 -23
- package/src/core/watermarkProcessor.js +1446 -125
- package/src/shared/pageImageReplacement.js +8 -12
- package/src/userscript/index.js +10 -5
package/dist/video-app.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pilio/gemini-watermark-remover",
|
|
3
3
|
"description": "Automatically removes watermarks from Gemini AI generated images",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.32",
|
|
5
5
|
"author": "GargantuaX",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"files": [
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
"probe:tm:profile": "node scripts/open-tampermonkey-profile.js",
|
|
103
103
|
"probe:tm:setup": "node scripts/tampermonkey-smoke.js setup",
|
|
104
104
|
"probe:real-page:compare": "node scripts/real-page-pixel-compare.js",
|
|
105
|
+
"probe:real-page:copy-download": "node scripts/real-page-copy-download-probe.js",
|
|
105
106
|
"benchmark:samples": "node scripts/sample-benchmark.js",
|
|
106
107
|
"benchmark:userscript": "node scripts/userscript-benchmark.js",
|
|
107
108
|
"benchmark:online-sample:gate": "node scripts/gate-online-gemini-watermark-sample-benchmark.js",
|
|
@@ -196,6 +196,52 @@ export function computeSizeAdjustedConfidence(confidence, size, referenceSize =
|
|
|
196
196
|
return confidence * sizeWeight;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
function compareAdaptiveCandidatePriority(left, right) {
|
|
200
|
+
const leftScore = Number.isFinite(left?.adjustedScore)
|
|
201
|
+
? left.adjustedScore
|
|
202
|
+
: computeSizeAdjustedConfidence(left?.confidence, left?.size);
|
|
203
|
+
const rightScore = Number.isFinite(right?.adjustedScore)
|
|
204
|
+
? right.adjustedScore
|
|
205
|
+
: computeSizeAdjustedConfidence(right?.confidence, right?.size);
|
|
206
|
+
if (Math.abs(leftScore - rightScore) > 1e-12) {
|
|
207
|
+
return leftScore - rightScore;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const leftSize = Number.isFinite(left?.size) ? left.size : 0;
|
|
211
|
+
const rightSize = Number.isFinite(right?.size) ? right.size : 0;
|
|
212
|
+
const leftDistance = Math.abs(leftSize - REFERENCE_WATERMARK_SIZE);
|
|
213
|
+
const rightDistance = Math.abs(rightSize - REFERENCE_WATERMARK_SIZE);
|
|
214
|
+
if (leftDistance !== rightDistance) {
|
|
215
|
+
return rightDistance - leftDistance;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const leftConfidence = Number.isFinite(left?.confidence) ? left.confidence : 0;
|
|
219
|
+
const rightConfidence = Number.isFinite(right?.confidence) ? right.confidence : 0;
|
|
220
|
+
if (leftConfidence !== rightConfidence) {
|
|
221
|
+
return leftConfidence - rightConfidence;
|
|
222
|
+
}
|
|
223
|
+
if (leftSize !== rightSize) {
|
|
224
|
+
return leftSize - rightSize;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const leftX = Number.isFinite(left?.x) ? left.x : Infinity;
|
|
228
|
+
const rightX = Number.isFinite(right?.x) ? right.x : Infinity;
|
|
229
|
+
if (leftX !== rightX) {
|
|
230
|
+
return rightX - leftX;
|
|
231
|
+
}
|
|
232
|
+
const leftY = Number.isFinite(left?.y) ? left.y : Infinity;
|
|
233
|
+
const rightY = Number.isFinite(right?.y) ? right.y : Infinity;
|
|
234
|
+
return rightY - leftY;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function selectAdaptiveFineCandidate(currentBest, candidate) {
|
|
238
|
+
if (!currentBest) return candidate;
|
|
239
|
+
if (!candidate) return currentBest;
|
|
240
|
+
return compareAdaptiveCandidatePriority(candidate, currentBest) > 0
|
|
241
|
+
? candidate
|
|
242
|
+
: currentBest;
|
|
243
|
+
}
|
|
244
|
+
|
|
199
245
|
function buildSeedConfigs(width, height, defaultConfig) {
|
|
200
246
|
// Start adaptive search from both the coarse default anchor and any
|
|
201
247
|
// catalog-projected anchors for official or near-official Gemini sizes.
|
|
@@ -445,10 +491,10 @@ export function detectAdaptiveWatermarkRegion({
|
|
|
445
491
|
})
|
|
446
492
|
.filter(Boolean);
|
|
447
493
|
|
|
448
|
-
const bestSeed = seedCandidates.reduce(
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
494
|
+
const bestSeed = seedCandidates.reduce(
|
|
495
|
+
(best, candidate) => selectAdaptiveFineCandidate(best, candidate),
|
|
496
|
+
null
|
|
497
|
+
);
|
|
452
498
|
if (bestSeed && bestSeed.confidence >= threshold + 0.08) {
|
|
453
499
|
return {
|
|
454
500
|
found: true,
|
|
@@ -483,7 +529,7 @@ export function detectAdaptiveWatermarkRegion({
|
|
|
483
529
|
const topK = [];
|
|
484
530
|
const pushTopK = (candidate) => {
|
|
485
531
|
topK.push(candidate);
|
|
486
|
-
topK.sort((
|
|
532
|
+
topK.sort((left, right) => -compareAdaptiveCandidatePriority(left, right));
|
|
487
533
|
if (topK.length > 5) topK.length = 5;
|
|
488
534
|
};
|
|
489
535
|
|
|
@@ -545,14 +591,12 @@ export function detectAdaptiveWatermarkRegion({
|
|
|
545
591
|
const score = scoreCandidate(context, tpl.alpha, tpl.grad, { x, y, size });
|
|
546
592
|
if (!score) continue;
|
|
547
593
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
};
|
|
555
|
-
}
|
|
594
|
+
best = selectAdaptiveFineCandidate(best, {
|
|
595
|
+
x,
|
|
596
|
+
y,
|
|
597
|
+
size,
|
|
598
|
+
...score
|
|
599
|
+
});
|
|
556
600
|
}
|
|
557
601
|
}
|
|
558
602
|
}
|
|
@@ -5,8 +5,13 @@ import { createRepairTrialFromStages } from './pipelineRepairTrial.js';
|
|
|
5
5
|
|
|
6
6
|
const NEW_MARGIN_96_SIZE = 96;
|
|
7
7
|
const NEW_MARGIN_96_MARGIN = 192;
|
|
8
|
-
const HIGH_RISK_NEW_MARGIN_MIN_SPATIAL = 0.4;
|
|
9
|
-
const HIGH_RISK_NEW_MARGIN_MIN_GRADIENT = 0.08;
|
|
8
|
+
const HIGH_RISK_NEW_MARGIN_MIN_SPATIAL = 0.4;
|
|
9
|
+
const HIGH_RISK_NEW_MARGIN_MIN_GRADIENT = 0.08;
|
|
10
|
+
const SAFE_EXACT_NEW_MARGIN_MIN_SPATIAL = 0.18;
|
|
11
|
+
const SAFE_EXACT_NEW_MARGIN_MIN_GRADIENT = 0.05;
|
|
12
|
+
const SAFE_EXACT_NEW_MARGIN_MIN_IMPROVEMENT = 0.1;
|
|
13
|
+
const SAFE_EXACT_NEW_MARGIN_MAX_PROCESSED_SPATIAL = 0.32;
|
|
14
|
+
const SAFE_EXACT_NEW_MARGIN_MAX_PROCESSED_GRADIENT = 0.05;
|
|
10
15
|
const DEFAULT_ALPHA_NEW_MARGIN_MAX_SPATIAL_RESIDUAL = 0.18;
|
|
11
16
|
const DEFAULT_ALPHA_NEW_MARGIN_MAX_GRADIENT_RESIDUAL = 0.08;
|
|
12
17
|
const DEFAULT_ALPHA_NEW_MARGIN_MIN_IMPROVEMENT = 0.12;
|
|
@@ -40,11 +45,30 @@ export function isNewMarginAlphaVariantTrial(candidate) {
|
|
|
40
45
|
config.alphaVariant === '20260520';
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
export function isDefaultAlphaNewMarginTrial(candidate) {
|
|
44
|
-
const config = getConfig(candidate);
|
|
45
|
-
return isNewMargin96Candidate(candidate) &&
|
|
46
|
-
!config.alphaVariant;
|
|
47
|
-
}
|
|
48
|
+
export function isDefaultAlphaNewMarginTrial(candidate) {
|
|
49
|
+
const config = getConfig(candidate);
|
|
50
|
+
return isNewMargin96Candidate(candidate) &&
|
|
51
|
+
!config.alphaVariant;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function isNewMarginVariantFamilyCandidate(candidate) {
|
|
55
|
+
const config = getConfig(candidate);
|
|
56
|
+
const provenance = getProvenance(candidate);
|
|
57
|
+
return config.marginRight === NEW_MARGIN_96_MARGIN &&
|
|
58
|
+
config.marginBottom === NEW_MARGIN_96_MARGIN &&
|
|
59
|
+
(config.alphaVariant === '20260520' || provenance.alphaVariant === '20260520');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function hasSafeExactNewMarginVariantRecovery(candidate) {
|
|
63
|
+
if (!isNewMarginAlphaVariantTrial(candidate)) return false;
|
|
64
|
+
if (candidate?.damage?.safe !== true) return false;
|
|
65
|
+
|
|
66
|
+
return numberOr(candidate?.originalSpatialScore) >= SAFE_EXACT_NEW_MARGIN_MIN_SPATIAL &&
|
|
67
|
+
numberOr(candidate?.originalGradientScore) >= SAFE_EXACT_NEW_MARGIN_MIN_GRADIENT &&
|
|
68
|
+
numberOr(candidate?.improvement, -Infinity) >= SAFE_EXACT_NEW_MARGIN_MIN_IMPROVEMENT &&
|
|
69
|
+
Math.abs(numberOr(candidate?.processedSpatialScore, Infinity)) <= SAFE_EXACT_NEW_MARGIN_MAX_PROCESSED_SPATIAL &&
|
|
70
|
+
Math.max(0, numberOr(candidate?.processedGradientScore, Infinity)) <= SAFE_EXACT_NEW_MARGIN_MAX_PROCESSED_GRADIENT;
|
|
71
|
+
}
|
|
48
72
|
|
|
49
73
|
export function hasClearedResidual(candidate) {
|
|
50
74
|
return candidate?.residual?.cleared === true ||
|
|
@@ -61,13 +85,14 @@ export function hasSafeDefaultAlphaNewMarginResidual(candidate) {
|
|
|
61
85
|
numberOr(candidate?.improvement, -Infinity) >= DEFAULT_ALPHA_NEW_MARGIN_MIN_IMPROVEMENT;
|
|
62
86
|
}
|
|
63
87
|
|
|
64
|
-
export function hasHighRiskNewMarginPositiveEvidence(candidate) {
|
|
65
|
-
if (getProvenance(candidate).darkPolarity === true) return true;
|
|
66
|
-
if (!
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
numberOr(candidate?.originalSpatialScore) >= HIGH_RISK_NEW_MARGIN_MIN_SPATIAL;
|
|
70
|
-
|
|
88
|
+
export function hasHighRiskNewMarginPositiveEvidence(candidate) {
|
|
89
|
+
if (getProvenance(candidate).darkPolarity === true) return true;
|
|
90
|
+
if (!isNewMarginVariantFamilyCandidate(candidate) && !isDefaultAlphaNewMarginTrial(candidate)) return true;
|
|
91
|
+
|
|
92
|
+
const hasStrongEvidence = numberOr(candidate?.originalGradientScore) >= HIGH_RISK_NEW_MARGIN_MIN_GRADIENT ||
|
|
93
|
+
numberOr(candidate?.originalSpatialScore) >= HIGH_RISK_NEW_MARGIN_MIN_SPATIAL;
|
|
94
|
+
return hasStrongEvidence || hasSafeExactNewMarginVariantRecovery(candidate);
|
|
95
|
+
}
|
|
71
96
|
|
|
72
97
|
export function shouldFailClosedForVisibleResidualUnsafeDamage({
|
|
73
98
|
selectedTrial = null,
|
|
@@ -124,10 +149,11 @@ export function createCandidateEvaluation({
|
|
|
124
149
|
provenance,
|
|
125
150
|
originalSpatialScore: originalScores?.spatialScore,
|
|
126
151
|
originalGradientScore: originalScores?.gradientScore,
|
|
127
|
-
processedSpatialScore: processedScores?.spatialScore,
|
|
128
|
-
processedGradientScore: processedScores?.gradientScore,
|
|
129
|
-
improvement
|
|
130
|
-
|
|
152
|
+
processedSpatialScore: processedScores?.spatialScore,
|
|
153
|
+
processedGradientScore: processedScores?.gradientScore,
|
|
154
|
+
improvement,
|
|
155
|
+
damage
|
|
156
|
+
};
|
|
131
157
|
const originalSpatial = numberOr(originalScores?.spatialScore);
|
|
132
158
|
const originalGradient = numberOr(originalScores?.gradientScore);
|
|
133
159
|
const processedSpatial = numberOr(processedScores?.spatialScore);
|
|
@@ -137,6 +137,8 @@ const BOTTOM_RIGHT_48_EVIDENCE_DOMINANCE_GRADIENT_ADVANTAGE = 0.12;
|
|
|
137
137
|
const BOTTOM_RIGHT_48_EVIDENCE_DOMINANCE_MAX_RESIDUAL_DELTA = 0.08;
|
|
138
138
|
const DARK_POLARITY_CATALOG_MIN_ORIGINAL_SPATIAL = 0.12;
|
|
139
139
|
const DARK_POLARITY_CATALOG_MIN_ORIGINAL_GRADIENT = 0.08;
|
|
140
|
+
const DARK_POLARITY_48_MIN_ORIGINAL_SPATIAL = 0.6;
|
|
141
|
+
const DARK_POLARITY_48_MIN_ORIGINAL_GRADIENT = 0.3;
|
|
140
142
|
const DARK_POLARITY_CATALOG_MAX_TEXTURE_FOR_WEAK_EVIDENCE = 0.25;
|
|
141
143
|
const DARK_POLARITY_MAX_NEAR_WHITE_RATIO_INCREASE_FOR_WEAK_EVIDENCE = 0.05;
|
|
142
144
|
const DARK_POLARITY_NEAR_WHITE_OVERRIDE_MIN_ORIGINAL_SPATIAL = 0.4;
|
|
@@ -183,6 +185,7 @@ const PREVIEW_ANCHOR_GAIN_SKIP_RESIDUAL_THRESHOLD = 0.24;
|
|
|
183
185
|
const PREVIEW_ANCHOR_GAIN_SKIP_GRADIENT_THRESHOLD = 0.24;
|
|
184
186
|
const CORE_ALPHA_PRIORITY_GAINS = Object.freeze([0.6, 1, 1.1, 1.15, 1.3, 0.45, 0.7, 0.85, 0.55]);
|
|
185
187
|
const CURRENT_LARGE_MARGIN_ULTRA_WEAK_ALPHA_GAINS = Object.freeze([0.25, 0.3, 0.35, 0.4]);
|
|
188
|
+
const DARK_POLARITY_48_ULTRA_WEAK_ALPHA_GAINS = Object.freeze([0.08, 0.1, 0.12, 0.15, 0.2]);
|
|
186
189
|
const STANDARD_ANCHOR_WEAK_ALPHA_RESCUE_GAINS = Object.freeze([0.55, 0.7, 0.85]);
|
|
187
190
|
const STANDARD_ANCHOR_WEAK_RESCUE_MAX_SPATIAL = 0.35;
|
|
188
191
|
const STANDARD_ANCHOR_WEAK_RESCUE_MAX_GRADIENT = 0.24;
|
|
@@ -393,13 +396,17 @@ function buildStandardCandidateSeeds({
|
|
|
393
396
|
}
|
|
394
397
|
|
|
395
398
|
if (shouldAddDarkPolaritySeed(candidateConfig)) {
|
|
399
|
+
const weakDarkPolarity48 = candidateConfig.logoSize === 48;
|
|
396
400
|
seeds.push({
|
|
397
401
|
...baseSeed,
|
|
398
402
|
alphaMap: createNegativeAlphaMap(alphaMap),
|
|
399
403
|
source: `${baseSeed.source}+dark-polarity`,
|
|
400
404
|
provenance: mergeCandidateProvenance(
|
|
401
405
|
baseSeed.provenance,
|
|
402
|
-
{
|
|
406
|
+
{
|
|
407
|
+
darkPolarity: true,
|
|
408
|
+
...(weakDarkPolarity48 ? { weakDarkPolarity48: true } : {})
|
|
409
|
+
}
|
|
403
410
|
)
|
|
404
411
|
});
|
|
405
412
|
}
|
|
@@ -409,9 +416,19 @@ function buildStandardCandidateSeeds({
|
|
|
409
416
|
}
|
|
410
417
|
|
|
411
418
|
function shouldAddDarkPolaritySeed(config) {
|
|
412
|
-
|
|
419
|
+
if (
|
|
420
|
+
config?.logoSize === 96 &&
|
|
413
421
|
config.marginRight === 192 &&
|
|
414
|
-
config.marginBottom === 192
|
|
422
|
+
config.marginBottom === 192
|
|
423
|
+
) {
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return config?.logoSize === 48 &&
|
|
428
|
+
config.marginRight >= 90 &&
|
|
429
|
+
config.marginRight <= 100 &&
|
|
430
|
+
config.marginBottom >= 90 &&
|
|
431
|
+
config.marginBottom <= 100;
|
|
415
432
|
}
|
|
416
433
|
|
|
417
434
|
const negativeAlphaMapCache = new WeakMap();
|
|
@@ -496,6 +513,23 @@ function resolveAlphaMapForSize(size, { alpha48, alpha96, getAlphaMap } = {}) {
|
|
|
496
513
|
return alpha96 ? interpolateAlphaMap(alpha96, 96, size) : null;
|
|
497
514
|
}
|
|
498
515
|
|
|
516
|
+
export function resolveSizeJitterAlphaMap(seed, size, {
|
|
517
|
+
alpha48,
|
|
518
|
+
alpha96,
|
|
519
|
+
getAlphaMap,
|
|
520
|
+
resolveAlphaMap = null
|
|
521
|
+
} = {}) {
|
|
522
|
+
const seedSize = Number(seed?.position?.width);
|
|
523
|
+
if (seed?.alphaMap && Number.isFinite(seedSize) && seedSize > 0) {
|
|
524
|
+
if (size === seedSize) return seed.alphaMap;
|
|
525
|
+
return interpolateAlphaMap(seed.alphaMap, seedSize, size);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return typeof resolveAlphaMap === 'function'
|
|
529
|
+
? resolveAlphaMap(size)
|
|
530
|
+
: resolveAlphaMapForSize(size, { alpha48, alpha96, getAlphaMap });
|
|
531
|
+
}
|
|
532
|
+
|
|
499
533
|
function resolveAlphaMapForConfig(config, {
|
|
500
534
|
alpha48,
|
|
501
535
|
alpha96,
|
|
@@ -642,7 +676,15 @@ function isWeakAlphaPrioritySeed(seed) {
|
|
|
642
676
|
seed.config.marginBottom === 96;
|
|
643
677
|
}
|
|
644
678
|
|
|
679
|
+
function isWeakDarkPolarity48Seed(seed) {
|
|
680
|
+
return seed?.provenance?.weakDarkPolarity48 === true;
|
|
681
|
+
}
|
|
682
|
+
|
|
645
683
|
function resolveStandardSeedAlphaPriorityGains(seed, alphaPriorityGains) {
|
|
684
|
+
if (isWeakDarkPolarity48Seed(seed)) {
|
|
685
|
+
return DARK_POLARITY_48_ULTRA_WEAK_ALPHA_GAINS;
|
|
686
|
+
}
|
|
687
|
+
|
|
646
688
|
const extras = isWeakAlphaPrioritySeed(seed)
|
|
647
689
|
? [
|
|
648
690
|
...CURRENT_LARGE_MARGIN_ULTRA_WEAK_ALPHA_GAINS,
|
|
@@ -857,7 +899,7 @@ function evaluateStandardTrialForSeed({
|
|
|
857
899
|
}
|
|
858
900
|
}
|
|
859
901
|
|
|
860
|
-
|
|
902
|
+
const selected = isWeakAlphaPrioritySeed(seed)
|
|
861
903
|
? bestWeakAlphaPriorityTrial ?? bestWeakAlphaRescueTrial ?? bestAcceptedTrial ?? fallbackTrial
|
|
862
904
|
: bestWeakAlphaPriorityTrial ??
|
|
863
905
|
(
|
|
@@ -867,6 +909,10 @@ function evaluateStandardTrialForSeed({
|
|
|
867
909
|
) ??
|
|
868
910
|
bestWeakAlphaRescueTrial ??
|
|
869
911
|
fallbackTrial;
|
|
912
|
+
|
|
913
|
+
return isWeakDarkPolarity48Seed(seed) && selected?.accepted !== true
|
|
914
|
+
? null
|
|
915
|
+
: selected;
|
|
870
916
|
}
|
|
871
917
|
|
|
872
918
|
export function evaluateRestorationCandidate({
|
|
@@ -994,11 +1040,40 @@ export function evaluateRestorationCandidate({
|
|
|
994
1040
|
const strongDarkPolarityOriginalEvidence =
|
|
995
1041
|
originalScores.spatialScore >= DARK_POLARITY_CATALOG_MIN_ORIGINAL_SPATIAL ||
|
|
996
1042
|
originalScores.gradientScore >= DARK_POLARITY_CATALOG_MIN_ORIGINAL_GRADIENT;
|
|
1043
|
+
const isLargeMargin48DarkPolarity =
|
|
1044
|
+
provenance?.darkPolarity === true &&
|
|
1045
|
+
config?.logoSize === 48 &&
|
|
1046
|
+
config.marginRight >= 90 &&
|
|
1047
|
+
config.marginRight <= 100 &&
|
|
1048
|
+
config.marginBottom >= 90 &&
|
|
1049
|
+
config.marginBottom <= 100;
|
|
1050
|
+
const largeMargin48DarkPolarityEvidenceAllowed =
|
|
1051
|
+
!isLargeMargin48DarkPolarity ||
|
|
1052
|
+
(
|
|
1053
|
+
originalScores.spatialScore >= DARK_POLARITY_48_MIN_ORIGINAL_SPATIAL &&
|
|
1054
|
+
originalScores.gradientScore >= DARK_POLARITY_48_MIN_ORIGINAL_GRADIENT
|
|
1055
|
+
);
|
|
1056
|
+
const weakDarkPolarity48ScopeAllowed =
|
|
1057
|
+
provenance?.weakDarkPolarity48 !== true ||
|
|
1058
|
+
(
|
|
1059
|
+
config?.logoSize === 48 &&
|
|
1060
|
+
config.marginRight >= 90 &&
|
|
1061
|
+
config.marginRight <= 100 &&
|
|
1062
|
+
config.marginBottom >= 90 &&
|
|
1063
|
+
config.marginBottom <= 100 &&
|
|
1064
|
+
alphaGain <= 0.2
|
|
1065
|
+
);
|
|
997
1066
|
const darkPolarityCatalogEvidenceAllowed =
|
|
998
1067
|
provenance?.darkPolarity !== true ||
|
|
999
1068
|
provenance?.catalogVariant !== true ||
|
|
1000
|
-
|
|
1001
|
-
|
|
1069
|
+
(
|
|
1070
|
+
weakDarkPolarity48ScopeAllowed &&
|
|
1071
|
+
largeMargin48DarkPolarityEvidenceAllowed &&
|
|
1072
|
+
(
|
|
1073
|
+
strongDarkPolarityOriginalEvidence ||
|
|
1074
|
+
texturePenalty <= DARK_POLARITY_CATALOG_MAX_TEXTURE_FOR_WEAK_EVIDENCE
|
|
1075
|
+
)
|
|
1076
|
+
);
|
|
1002
1077
|
const strongDarkPolarityNearWhiteOverrideEvidence =
|
|
1003
1078
|
originalScores.spatialScore >= DARK_POLARITY_NEAR_WHITE_OVERRIDE_MIN_ORIGINAL_SPATIAL ||
|
|
1004
1079
|
originalScores.gradientScore >= DARK_POLARITY_NEAR_WHITE_OVERRIDE_MIN_ORIGINAL_GRADIENT;
|
|
@@ -1320,11 +1395,35 @@ function compareSameAnchorCandidateRanking(currentBest, candidate) {
|
|
|
1320
1395
|
return compareRankingKey(candidate.rankingKey, currentBest.rankingKey);
|
|
1321
1396
|
}
|
|
1322
1397
|
|
|
1398
|
+
function shouldPreserveExactNewMarginVariant(exactCandidate, competingCandidate) {
|
|
1399
|
+
const exactConfig = exactCandidate?.config ?? {};
|
|
1400
|
+
const competingConfig = competingCandidate?.config ?? {};
|
|
1401
|
+
const exactVariant = exactConfig.alphaVariant ?? exactCandidate?.provenance?.alphaVariant;
|
|
1402
|
+
const competingVariant = competingConfig.alphaVariant ?? competingCandidate?.provenance?.alphaVariant;
|
|
1403
|
+
|
|
1404
|
+
if (exactCandidate?.accepted !== true || exactCandidate?.damage?.safe !== true) return false;
|
|
1405
|
+
if (exactConfig.logoSize !== 96 || exactConfig.marginRight !== 192 || exactConfig.marginBottom !== 192) {
|
|
1406
|
+
return false;
|
|
1407
|
+
}
|
|
1408
|
+
if (exactVariant !== '20260520') return false;
|
|
1409
|
+
if (competingCandidate?.provenance?.sizeJitter !== true) return false;
|
|
1410
|
+
if (competingConfig.marginRight !== 192 || competingConfig.marginBottom !== 192) return false;
|
|
1411
|
+
if (competingVariant !== exactVariant) return false;
|
|
1412
|
+
|
|
1413
|
+
return !hasMuchStrongerOriginalSignal(competingCandidate, exactCandidate);
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1323
1416
|
export function pickBetterCandidate(currentBest, candidate, minCostDelta = 0.005) {
|
|
1324
1417
|
if (!candidate?.accepted) return currentBest;
|
|
1325
1418
|
if (!currentBest) return candidate;
|
|
1326
1419
|
const evaluationDecision = arbitrateCandidateByEvaluation(currentBest, candidate);
|
|
1327
1420
|
if (evaluationDecision) return evaluationDecision;
|
|
1421
|
+
if (shouldPreserveExactNewMarginVariant(currentBest, candidate)) {
|
|
1422
|
+
return currentBest;
|
|
1423
|
+
}
|
|
1424
|
+
if (shouldPreserveExactNewMarginVariant(candidate, currentBest)) {
|
|
1425
|
+
return candidate;
|
|
1426
|
+
}
|
|
1328
1427
|
if (shouldPreserveCatalogOriginalSignal(currentBest, candidate)) {
|
|
1329
1428
|
return currentBest;
|
|
1330
1429
|
}
|
|
@@ -1975,13 +2074,12 @@ function searchStandardSizeJitterCandidate({
|
|
|
1975
2074
|
if (candidatePosition.x + candidatePosition.width > originalImageData.width) continue;
|
|
1976
2075
|
if (candidatePosition.y + candidatePosition.height > originalImageData.height) continue;
|
|
1977
2076
|
|
|
1978
|
-
const candidateAlphaMap =
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
});
|
|
2077
|
+
const candidateAlphaMap = resolveSizeJitterAlphaMap(seed, size, {
|
|
2078
|
+
alpha48,
|
|
2079
|
+
alpha96,
|
|
2080
|
+
getAlphaMap,
|
|
2081
|
+
resolveAlphaMap
|
|
2082
|
+
});
|
|
1985
2083
|
if (!candidateAlphaMap) continue;
|
|
1986
2084
|
|
|
1987
2085
|
const candidate = evaluateRestorationCandidate({
|
|
@@ -1989,11 +2087,10 @@ function searchStandardSizeJitterCandidate({
|
|
|
1989
2087
|
alphaMap: candidateAlphaMap,
|
|
1990
2088
|
position: candidatePosition,
|
|
1991
2089
|
source: `${seed.source}+size`,
|
|
1992
|
-
config: {
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
},
|
|
2090
|
+
config: {
|
|
2091
|
+
...seed.config,
|
|
2092
|
+
logoSize: size
|
|
2093
|
+
},
|
|
1997
2094
|
baselineNearBlackRatio: calculateNearBlackRatio(originalImageData, candidatePosition),
|
|
1998
2095
|
adaptiveConfidence,
|
|
1999
2096
|
provenance: mergeCandidateProvenance(seed.provenance, { sizeJitter: true }),
|
|
@@ -27,6 +27,14 @@ function createSelectedCandidate(best) {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
function findDarkBackgroundSupportConvergence(meta = {}) {
|
|
31
|
+
const stages = Array.isArray(meta.alphaAdjustmentStages)
|
|
32
|
+
? meta.alphaAdjustmentStages
|
|
33
|
+
: [];
|
|
34
|
+
const convergence = stages.at(-1)?.darkBackgroundSupportConvergence;
|
|
35
|
+
return convergence?.accepted === true ? convergence : null;
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
function createRuntimeFailureResult({
|
|
31
39
|
createRejectedResult,
|
|
32
40
|
originalImageData,
|
|
@@ -42,6 +50,26 @@ function createRuntimeFailureResult({
|
|
|
42
50
|
});
|
|
43
51
|
}
|
|
44
52
|
|
|
53
|
+
function createNoWatermarkResult({
|
|
54
|
+
createRejectedResult,
|
|
55
|
+
originalImageData,
|
|
56
|
+
collection,
|
|
57
|
+
debugTimings
|
|
58
|
+
}) {
|
|
59
|
+
const selection = collection?.automaticSelection ?? collection?.fixedSelection ?? {};
|
|
60
|
+
return createRejectedResult({
|
|
61
|
+
imageData: originalImageData,
|
|
62
|
+
debugTimings,
|
|
63
|
+
reason: 'no-watermark-detected',
|
|
64
|
+
adaptiveConfidence: selection.adaptiveConfidence ?? null,
|
|
65
|
+
originalSpatialScore: selection.standardSpatialScore ?? null,
|
|
66
|
+
originalGradientScore: selection.standardGradientScore ?? null,
|
|
67
|
+
source: 'skipped',
|
|
68
|
+
decisionTier: selection.decisionTier ?? 'insufficient',
|
|
69
|
+
selectionDebug: null
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
45
73
|
function notifyCandidateCompleted({ options, candidate, debugTimings }) {
|
|
46
74
|
if (typeof options?.onCandidateCompleted !== 'function') return;
|
|
47
75
|
|
|
@@ -55,6 +83,41 @@ function notifyCandidateCompleted({ options, candidate, debugTimings }) {
|
|
|
55
83
|
}
|
|
56
84
|
}
|
|
57
85
|
|
|
86
|
+
function appendUniqueRiskFlag(flags, flag) {
|
|
87
|
+
const normalized = Array.isArray(flags) ? flags : [];
|
|
88
|
+
return normalized.includes(flag) ? normalized : [...normalized, flag];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function attachPresenceBestEffortMeta(meta, collection) {
|
|
92
|
+
if (collection?.bestEffortFallback !== true) return meta;
|
|
93
|
+
|
|
94
|
+
const riskFlag = 'unconfirmed-watermark-presence';
|
|
95
|
+
const decisionPath = meta?.decisionPath && typeof meta.decisionPath === 'object'
|
|
96
|
+
? {
|
|
97
|
+
...meta.decisionPath,
|
|
98
|
+
riskFlags: appendUniqueRiskFlag(meta.decisionPath.riskFlags, riskFlag),
|
|
99
|
+
evaluation: meta.decisionPath.evaluation &&
|
|
100
|
+
typeof meta.decisionPath.evaluation === 'object'
|
|
101
|
+
? {
|
|
102
|
+
...meta.decisionPath.evaluation,
|
|
103
|
+
riskFlags: appendUniqueRiskFlag(
|
|
104
|
+
meta.decisionPath.evaluation.riskFlags,
|
|
105
|
+
riskFlag
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
: meta.decisionPath.evaluation
|
|
109
|
+
}
|
|
110
|
+
: meta?.decisionPath;
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
...meta,
|
|
114
|
+
presenceConfirmed: false,
|
|
115
|
+
bestEffortReason:
|
|
116
|
+
collection.bestEffortReason ?? 'presence-witness-unconfirmed',
|
|
117
|
+
decisionPath
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
58
121
|
export function runImageWatermarkPipeline({
|
|
59
122
|
imageData,
|
|
60
123
|
options = {},
|
|
@@ -119,6 +182,26 @@ export function runImageWatermarkPipeline({
|
|
|
119
182
|
debugTimings.generatedCandidateCount = hypotheses.length;
|
|
120
183
|
debugTimings.earlyExitReason = null;
|
|
121
184
|
}
|
|
185
|
+
if (
|
|
186
|
+
collection?.presenceConfirmed === false &&
|
|
187
|
+
collection?.bestEffortFallback !== true
|
|
188
|
+
) {
|
|
189
|
+
if (debugTimingsEnabled) {
|
|
190
|
+
debugTimings.candidateExecutionMs = 0;
|
|
191
|
+
debugTimings.executedCandidateCount = 0;
|
|
192
|
+
debugTimings.completedCandidateCount = 0;
|
|
193
|
+
debugTimings.failedCandidateCount = 0;
|
|
194
|
+
debugTimings.candidateRankingMs = 0;
|
|
195
|
+
debugTimings.earlyExitReason = 'no-watermark-detected';
|
|
196
|
+
debugTimings.totalMs = nowMs() - totalStartedAt;
|
|
197
|
+
}
|
|
198
|
+
return createNoWatermarkResult({
|
|
199
|
+
createRejectedResult,
|
|
200
|
+
originalImageData,
|
|
201
|
+
collection,
|
|
202
|
+
debugTimings
|
|
203
|
+
});
|
|
204
|
+
}
|
|
122
205
|
|
|
123
206
|
const completed = [];
|
|
124
207
|
const failures = [];
|
|
@@ -135,7 +218,9 @@ export function runImageWatermarkPipeline({
|
|
|
135
218
|
debugTimingsEnabled,
|
|
136
219
|
visualPostProcessingEnabled,
|
|
137
220
|
cleanupConfig,
|
|
138
|
-
createAcceptedPipelineDependencies
|
|
221
|
+
createAcceptedPipelineDependencies: () => (
|
|
222
|
+
createAcceptedPipelineDependencies(hypothesis)
|
|
223
|
+
),
|
|
139
224
|
runAcceptedPipeline,
|
|
140
225
|
createAcceptedFinalResult
|
|
141
226
|
});
|
|
@@ -148,7 +233,16 @@ export function runImageWatermarkPipeline({
|
|
|
148
233
|
qualitySignals: measureCandidate({
|
|
149
234
|
originalImageData,
|
|
150
235
|
candidateImageData: completedCandidate.result.imageData,
|
|
151
|
-
hypothesis
|
|
236
|
+
hypothesis,
|
|
237
|
+
finalCandidate: {
|
|
238
|
+
position: completedCandidate.pipelineState?.position,
|
|
239
|
+
alphaMap: completedCandidate.pipelineState?.alphaMap,
|
|
240
|
+
alphaGain: completedCandidate.pipelineState?.alphaGain,
|
|
241
|
+
darkBackgroundSupportConvergence:
|
|
242
|
+
findDarkBackgroundSupportConvergence(
|
|
243
|
+
completedCandidate.result.meta
|
|
244
|
+
)
|
|
245
|
+
}
|
|
152
246
|
})
|
|
153
247
|
};
|
|
154
248
|
completed.push(candidate);
|
|
@@ -197,13 +291,14 @@ export function runImageWatermarkPipeline({
|
|
|
197
291
|
}
|
|
198
292
|
|
|
199
293
|
const candidateSummaries = createSummaries(ranked, failures);
|
|
200
|
-
const
|
|
294
|
+
const selectionMeta = attachSelectionMeta(best.result.meta, {
|
|
201
295
|
qualityStatus: best.qualitySignals?.qualityStatus,
|
|
202
296
|
selectionConfidence: best.selectionConfidence,
|
|
203
297
|
selectedCandidate: createSelectedCandidate(best),
|
|
204
298
|
qualitySignals: best.qualitySignals,
|
|
205
299
|
candidateSummaries
|
|
206
300
|
});
|
|
301
|
+
const meta = attachPresenceBestEffortMeta(selectionMeta, collection);
|
|
207
302
|
if (debugTimingsEnabled) {
|
|
208
303
|
debugTimings.candidateRankingMs = nowMs() - rankingStartedAt;
|
|
209
304
|
debugTimings.totalMs = nowMs() - totalStartedAt;
|
|
@@ -96,11 +96,15 @@ export function runAcceptedAlphaRepairPipeline({
|
|
|
96
96
|
originalGradientScore: current.originalGradientScore,
|
|
97
97
|
calculateNearBlackRatio: metrics.calculateNearBlackRatio,
|
|
98
98
|
acceptCurrentAlphaTrialResult,
|
|
99
|
-
debugTimings,
|
|
100
|
-
debugTimingsEnabled,
|
|
101
|
-
refiners: {
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
debugTimings,
|
|
100
|
+
debugTimingsEnabled,
|
|
101
|
+
refiners: {
|
|
102
|
+
refineLargeMargin48ProfileAlphaRescue:
|
|
103
|
+
refiners.refineLargeMargin48ProfileAlphaRescue,
|
|
104
|
+
fineTuneEvidenceGatedLocalAlpha:
|
|
105
|
+
refiners.fineTuneEvidenceGatedLocalAlpha,
|
|
106
|
+
recalibrateOverSubtractedAlpha: refiners.recalibrateOverSubtractedAlpha,
|
|
107
|
+
fineTuneDarkCatalogAlpha: refiners.fineTuneDarkCatalogAlpha,
|
|
104
108
|
fineTuneWeakPositiveResidualAlpha: refiners.fineTuneWeakPositiveResidualAlpha
|
|
105
109
|
}
|
|
106
110
|
});
|