@pilio/gemini-watermark-remover 1.0.26 → 1.0.27
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/package.json
CHANGED
|
@@ -147,12 +147,12 @@ const PREVIEW_ANCHOR_MIN_SIZE_RATIO = 0.55;
|
|
|
147
147
|
const PREVIEW_ANCHOR_MARGIN_WINDOW = 16;
|
|
148
148
|
const PREVIEW_ANCHOR_MARGIN_EXTENSION = 8;
|
|
149
149
|
const PREVIEW_ANCHOR_SIZE_STEP = 2;
|
|
150
|
-
const PREVIEW_ANCHOR_MARGIN_STEP = 2;
|
|
151
|
-
const PREVIEW_ANCHOR_TOP_K = 8;
|
|
152
|
-
const PREVIEW_ANCHOR_MIN_SCORE = 0.2;
|
|
153
|
-
const PREVIEW_ANCHOR_LOCAL_DELTAS = [-1, 0, 1];
|
|
154
|
-
const PREVIEW_TEMPLATE_ALIGN_SHIFTS = [-1, -0.5, 0, 0.5, 1];
|
|
155
|
-
const PREVIEW_TEMPLATE_ALIGN_SCALES = [0.985, 1, 1.015];
|
|
150
|
+
const PREVIEW_ANCHOR_MARGIN_STEP = 2;
|
|
151
|
+
const PREVIEW_ANCHOR_TOP_K = 8;
|
|
152
|
+
const PREVIEW_ANCHOR_MIN_SCORE = 0.2;
|
|
153
|
+
const PREVIEW_ANCHOR_LOCAL_DELTAS = [-1, 0, 1];
|
|
154
|
+
const PREVIEW_TEMPLATE_ALIGN_SHIFTS = [-1, -0.5, 0, 0.5, 1];
|
|
155
|
+
const PREVIEW_TEMPLATE_ALIGN_SCALES = [0.985, 1, 1.015];
|
|
156
156
|
const PREVIEW_ANCHOR_GAIN_SKIP_RESIDUAL_THRESHOLD = 0.24;
|
|
157
157
|
const PREVIEW_ANCHOR_GAIN_SKIP_GRADIENT_THRESHOLD = 0.24;
|
|
158
158
|
const CORE_ALPHA_PRIORITY_GAINS = Object.freeze([0.6, 1, 1.1, 1.15, 1.3, 0.45, 0.7, 0.85, 0.55]);
|
|
@@ -103,6 +103,13 @@ const KNOWN_48_LUMA_EDGE_PRESETS = Object.freeze([
|
|
|
103
103
|
{ name: 'mid', minAlpha: 0.012, maxAlpha: 0.7, referenceAlphaMax: 0.04, radius: 3, strength: 0.42, colorSigma: 34, maxDelta: 32 },
|
|
104
104
|
{ name: 'wide', minAlpha: 0.012, maxAlpha: 0.7, referenceAlphaMax: 0.055, radius: 4, strength: 0.48, colorSigma: 34, maxDelta: 40 }
|
|
105
105
|
]);
|
|
106
|
+
const KNOWN_48_MID_CORE_BIAS_STRENGTH = 0.25;
|
|
107
|
+
const KNOWN_48_MID_CORE_BIAS_MIN_HALO = 8;
|
|
108
|
+
const KNOWN_48_MID_CORE_BIAS_MIN_HALO_REDUCTION = 0.5;
|
|
109
|
+
const KNOWN_48_MID_CORE_BIAS_MAX_GRADIENT_DRIFT = 0.01;
|
|
110
|
+
const KNOWN_48_MID_CORE_BIAS_MAX_SPATIAL_DRIFT = 0.02;
|
|
111
|
+
const KNOWN_48_MID_CORE_BIAS_MAX_ARTIFACT_DRIFT = 0.001;
|
|
112
|
+
const KNOWN_48_MID_CORE_BIAS_MAX_NEW_CLIP_DRIFT = 0.001;
|
|
106
113
|
const PREVIEW_EDGE_CLEANUP_SPATIAL_THRESHOLD = 0.08;
|
|
107
114
|
const PREVIEW_EDGE_CLEANUP_GRADIENT_THRESHOLD = 0.1;
|
|
108
115
|
const PREVIEW_EDGE_CLEANUP_MIN_GRADIENT_IMPROVEMENT = 0.03;
|
|
@@ -1477,6 +1484,171 @@ function refineKnown48LumaEdgeResidual({
|
|
|
1477
1484
|
return best;
|
|
1478
1485
|
}
|
|
1479
1486
|
|
|
1487
|
+
function alphaBandBiasWeight(alpha, {
|
|
1488
|
+
outerMinAlpha = 0.12,
|
|
1489
|
+
innerMinAlpha = 0.18,
|
|
1490
|
+
innerMaxAlpha = 0.35,
|
|
1491
|
+
outerMaxAlpha = 0.42
|
|
1492
|
+
} = {}) {
|
|
1493
|
+
if (alpha < outerMinAlpha || alpha > outerMaxAlpha) return 0;
|
|
1494
|
+
if (alpha >= innerMinAlpha && alpha <= innerMaxAlpha) return 1;
|
|
1495
|
+
if (alpha < innerMinAlpha) {
|
|
1496
|
+
return smoothstep(outerMinAlpha, innerMinAlpha, alpha);
|
|
1497
|
+
}
|
|
1498
|
+
return 1 - smoothstep(innerMaxAlpha, outerMaxAlpha, alpha);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
function smoothstep(edge0, edge1, value) {
|
|
1502
|
+
if (edge0 === edge1) return value >= edge1 ? 1 : 0;
|
|
1503
|
+
const t = clamp01((value - edge0) / (edge1 - edge0));
|
|
1504
|
+
return t * t * (3 - 2 * t);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
function applyMidCoreBiasCorrection({ sourceImageData, alphaMap, position, positiveHaloLum, strength }) {
|
|
1508
|
+
const candidate = cloneImageData(sourceImageData);
|
|
1509
|
+
const bias = Math.max(0, positiveHaloLum) * strength;
|
|
1510
|
+
if (bias <= 0) return candidate;
|
|
1511
|
+
|
|
1512
|
+
for (let row = 0; row < position.height; row++) {
|
|
1513
|
+
for (let col = 0; col < position.width; col++) {
|
|
1514
|
+
const localIndex = row * position.width + col;
|
|
1515
|
+
const alpha = alphaMap[localIndex] ?? 0;
|
|
1516
|
+
const weight = alphaBandBiasWeight(alpha);
|
|
1517
|
+
if (weight <= 0) continue;
|
|
1518
|
+
|
|
1519
|
+
const pixelIndex = ((position.y + row) * candidate.width + position.x + col) * 4;
|
|
1520
|
+
const delta = bias * weight;
|
|
1521
|
+
candidate.data[pixelIndex] = clampChannel(candidate.data[pixelIndex] - delta);
|
|
1522
|
+
candidate.data[pixelIndex + 1] = clampChannel(candidate.data[pixelIndex + 1] - delta);
|
|
1523
|
+
candidate.data[pixelIndex + 2] = clampChannel(candidate.data[pixelIndex + 2] - delta);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
return candidate;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
function positiveBandDelta(imageData, position, alphaMap, minAlpha, maxAlpha) {
|
|
1531
|
+
const halo = assessAlphaBandHalo({
|
|
1532
|
+
imageData,
|
|
1533
|
+
position,
|
|
1534
|
+
alphaMap,
|
|
1535
|
+
minAlpha,
|
|
1536
|
+
maxAlpha,
|
|
1537
|
+
outsideAlphaMax: 0.012,
|
|
1538
|
+
outerMargin: 4
|
|
1539
|
+
});
|
|
1540
|
+
return halo.positiveDeltaLum ?? 0;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
function hasDominantMidCoreHalo({ imageData, position, alphaMap }) {
|
|
1544
|
+
const edge = positiveBandDelta(imageData, position, alphaMap, 0.02, 0.12);
|
|
1545
|
+
const midCore = positiveBandDelta(imageData, position, alphaMap, 0.18, 0.35);
|
|
1546
|
+
const highCore = positiveBandDelta(imageData, position, alphaMap, 0.35, 0.78);
|
|
1547
|
+
return midCore > edge && midCore > highCore;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
function refineKnown48MidCoreBiasResidual({
|
|
1551
|
+
originalImageData,
|
|
1552
|
+
currentImageData,
|
|
1553
|
+
alphaMap,
|
|
1554
|
+
position,
|
|
1555
|
+
source,
|
|
1556
|
+
alphaGain,
|
|
1557
|
+
baselineSpatialScore,
|
|
1558
|
+
baselineGradientScore
|
|
1559
|
+
}) {
|
|
1560
|
+
if (
|
|
1561
|
+
position?.width < KNOWN_48_EDGE_CLEANUP_MIN_SIZE ||
|
|
1562
|
+
position?.width > KNOWN_48_EDGE_CLEANUP_MAX_SIZE ||
|
|
1563
|
+
typeof source !== 'string' ||
|
|
1564
|
+
!source.includes('edge-cleanup') ||
|
|
1565
|
+
source.includes('v2-small-edge-cleanup')
|
|
1566
|
+
) {
|
|
1567
|
+
return null;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
const baselineVisibility = assessWatermarkResidualVisibility({
|
|
1571
|
+
imageData: currentImageData,
|
|
1572
|
+
position,
|
|
1573
|
+
alphaMap
|
|
1574
|
+
});
|
|
1575
|
+
if (
|
|
1576
|
+
baselineVisibility?.visiblePositiveHalo !== true ||
|
|
1577
|
+
(baselineVisibility.positiveHaloLum ?? 0) < KNOWN_48_MID_CORE_BIAS_MIN_HALO ||
|
|
1578
|
+
!hasDominantMidCoreHalo({ imageData: currentImageData, position, alphaMap })
|
|
1579
|
+
) {
|
|
1580
|
+
return null;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
const baselineArtifacts = assessRemovalDiffArtifacts({
|
|
1584
|
+
originalImageData,
|
|
1585
|
+
candidateImageData: currentImageData,
|
|
1586
|
+
alphaMap,
|
|
1587
|
+
position,
|
|
1588
|
+
alphaGain
|
|
1589
|
+
});
|
|
1590
|
+
const baselineArtifactCost = Number(baselineArtifacts?.visualArtifactCost);
|
|
1591
|
+
if (!Number.isFinite(baselineArtifactCost)) return null;
|
|
1592
|
+
|
|
1593
|
+
const candidate = applyMidCoreBiasCorrection({
|
|
1594
|
+
sourceImageData: currentImageData,
|
|
1595
|
+
alphaMap,
|
|
1596
|
+
position,
|
|
1597
|
+
positiveHaloLum: baselineVisibility.positiveHaloLum,
|
|
1598
|
+
strength: KNOWN_48_MID_CORE_BIAS_STRENGTH
|
|
1599
|
+
});
|
|
1600
|
+
const spatialScore = computeRegionSpatialCorrelation({
|
|
1601
|
+
imageData: candidate,
|
|
1602
|
+
alphaMap,
|
|
1603
|
+
region: { x: position.x, y: position.y, size: position.width }
|
|
1604
|
+
});
|
|
1605
|
+
const gradientScore = computeRegionGradientCorrelation({
|
|
1606
|
+
imageData: candidate,
|
|
1607
|
+
alphaMap,
|
|
1608
|
+
region: { x: position.x, y: position.y, size: position.width }
|
|
1609
|
+
});
|
|
1610
|
+
const residualVisibility = assessWatermarkResidualVisibility({
|
|
1611
|
+
imageData: candidate,
|
|
1612
|
+
position,
|
|
1613
|
+
alphaMap
|
|
1614
|
+
});
|
|
1615
|
+
const artifacts = assessRemovalDiffArtifacts({
|
|
1616
|
+
originalImageData,
|
|
1617
|
+
candidateImageData: candidate,
|
|
1618
|
+
alphaMap,
|
|
1619
|
+
position,
|
|
1620
|
+
alphaGain
|
|
1621
|
+
});
|
|
1622
|
+
const artifactCost = Number(artifacts?.visualArtifactCost);
|
|
1623
|
+
if (!Number.isFinite(artifactCost)) return null;
|
|
1624
|
+
|
|
1625
|
+
const haloReduction = (baselineVisibility.positiveHaloLum ?? 0) - (residualVisibility?.positiveHaloLum ?? 0);
|
|
1626
|
+
const gradientDrift = gradientScore - baselineGradientScore;
|
|
1627
|
+
const spatialDrift = Math.abs(spatialScore) - Math.abs(baselineSpatialScore);
|
|
1628
|
+
const artifactDrift = artifactCost - baselineArtifactCost;
|
|
1629
|
+
const newClipDrift = (artifacts?.newlyClippedRatio ?? 0) - (baselineArtifacts?.newlyClippedRatio ?? 0);
|
|
1630
|
+
if (
|
|
1631
|
+
haloReduction < KNOWN_48_MID_CORE_BIAS_MIN_HALO_REDUCTION ||
|
|
1632
|
+
gradientDrift > KNOWN_48_MID_CORE_BIAS_MAX_GRADIENT_DRIFT ||
|
|
1633
|
+
spatialDrift > KNOWN_48_MID_CORE_BIAS_MAX_SPATIAL_DRIFT ||
|
|
1634
|
+
artifactDrift > KNOWN_48_MID_CORE_BIAS_MAX_ARTIFACT_DRIFT ||
|
|
1635
|
+
newClipDrift > KNOWN_48_MID_CORE_BIAS_MAX_NEW_CLIP_DRIFT
|
|
1636
|
+
) {
|
|
1637
|
+
return null;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
return {
|
|
1641
|
+
imageData: candidate,
|
|
1642
|
+
spatialScore,
|
|
1643
|
+
gradientScore,
|
|
1644
|
+
residualVisibility,
|
|
1645
|
+
cost: artifactCost,
|
|
1646
|
+
haloReduction,
|
|
1647
|
+
artifactDrift,
|
|
1648
|
+
newClipDrift
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1480
1652
|
function expandPosition(position, imageData, pad) {
|
|
1481
1653
|
const left = Math.max(0, position.x - pad);
|
|
1482
1654
|
const top = Math.max(0, position.y - pad);
|
|
@@ -4553,6 +4725,37 @@ export function processWatermarkImageData(imageData, options = {}) {
|
|
|
4553
4725
|
suppressionGain = originalSpatialScore - finalProcessedSpatialScore;
|
|
4554
4726
|
source = `${source}+quantized-body-correction`;
|
|
4555
4727
|
}
|
|
4728
|
+
|
|
4729
|
+
const midCoreBiasStartedAt = nowMs();
|
|
4730
|
+
const midCoreBiasCorrection = refineKnown48MidCoreBiasResidual({
|
|
4731
|
+
originalImageData,
|
|
4732
|
+
currentImageData: finalImageData,
|
|
4733
|
+
alphaMap,
|
|
4734
|
+
position,
|
|
4735
|
+
source,
|
|
4736
|
+
alphaGain,
|
|
4737
|
+
baselineSpatialScore: finalProcessedSpatialScore,
|
|
4738
|
+
baselineGradientScore: finalProcessedGradientScore
|
|
4739
|
+
});
|
|
4740
|
+
if (midCoreBiasCorrection) {
|
|
4741
|
+
recordAlphaAdjustmentStage({
|
|
4742
|
+
stage: 'known-48-mid-core-bias-correction',
|
|
4743
|
+
fromAlphaGain: alphaGain,
|
|
4744
|
+
toAlphaGain: alphaGain,
|
|
4745
|
+
beforeSpatialScore: finalProcessedSpatialScore,
|
|
4746
|
+
beforeGradientScore: finalProcessedGradientScore,
|
|
4747
|
+
afterSpatialScore: midCoreBiasCorrection.spatialScore,
|
|
4748
|
+
afterGradientScore: midCoreBiasCorrection.gradientScore,
|
|
4749
|
+
suppressionGain: originalSpatialScore - midCoreBiasCorrection.spatialScore,
|
|
4750
|
+
cost: midCoreBiasCorrection.cost,
|
|
4751
|
+
allowSameAlphaGain: true
|
|
4752
|
+
});
|
|
4753
|
+
finalImageData = midCoreBiasCorrection.imageData;
|
|
4754
|
+
finalProcessedSpatialScore = midCoreBiasCorrection.spatialScore;
|
|
4755
|
+
finalProcessedGradientScore = midCoreBiasCorrection.gradientScore;
|
|
4756
|
+
suppressionGain = originalSpatialScore - finalProcessedSpatialScore;
|
|
4757
|
+
source = `${source}+mid-core-bias`;
|
|
4758
|
+
}
|
|
4556
4759
|
if (debugTimingsEnabled) {
|
|
4557
4760
|
debugTimings.previewEdgeCleanupMs = previewEdgeCleanupElapsedMs;
|
|
4558
4761
|
debugTimings.smallPreviewRefinementMs = nowMs() - smallPreviewRefinementStartedAt;
|
|
@@ -4562,7 +4765,8 @@ export function processWatermarkImageData(imageData, options = {}) {
|
|
|
4562
4765
|
debugTimings.powerProfileRescueMs = boundaryRepairRescueStartedAt - powerProfileRescueStartedAt;
|
|
4563
4766
|
debugTimings.boundaryRepairRescueMs = darkHaloRescueStartedAt - boundaryRepairRescueStartedAt;
|
|
4564
4767
|
debugTimings.darkHaloRescueMs = quantizedBodyCorrectionStartedAt - darkHaloRescueStartedAt;
|
|
4565
|
-
debugTimings.quantizedBodyCorrectionMs =
|
|
4768
|
+
debugTimings.quantizedBodyCorrectionMs = midCoreBiasStartedAt - quantizedBodyCorrectionStartedAt;
|
|
4769
|
+
debugTimings.midCoreBiasCorrectionMs = nowMs() - midCoreBiasStartedAt;
|
|
4566
4770
|
debugTimings.totalMs = nowMs() - totalStartedAt;
|
|
4567
4771
|
}
|
|
4568
4772
|
|