Add real watermark fixtures and expand provider coverage
No files matched your search
@@ -203,9 +203,9 @@ to one provider.
|
||||
Sora covers the moving Sora 2 mascot and wordmark. Veo covers both the current
|
||||
four-point diamond and the legacy `Veo` text. Seedance covers the fixed boxed
|
||||
`AI` label, Dola covers the fixed `Dola AI` text, Hailuo AI covers the composite
|
||||
`MINIMAX | hailuo AI` label, and Kling AI covers the bottom-right `KLING AI`
|
||||
label with its version suffix. A completed encode is published atomically. No
|
||||
output is written when no stable mark is found.
|
||||
`MINIMAX | hailuo AI` label, and Kling AI covers the bottom-right `KLING AI` or
|
||||
`KlingAI` label with its version suffix. A completed encode is published
|
||||
atomically. No output is written when no stable mark is found.
|
||||
HDR, PQ/HLG, and greater-than-8-bit inputs are rejected before encoding rather
|
||||
than silently reduced through OpenCV's 8-bit BGR boundary.
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ data/
|
||||
fixtures/
|
||||
provenance/ Real format and provenance fixtures used by tests
|
||||
(source records live in fixtures/README.md)
|
||||
visible/ Synthetic per-mark example gallery (one committed example per
|
||||
registered visible mark; see fixtures/visible/README.md)
|
||||
visible/ Per-mark example gallery: one synthetic canonical example per
|
||||
registered mark plus documented provider originals where available
|
||||
(see fixtures/visible/README.md)
|
||||
calibration/
|
||||
<vendor>/ Minimal controlled inputs needed to rebuild detector assets
|
||||
synthid/
|
||||
@@ -24,6 +25,11 @@ data/
|
||||
Reproducible full-clip Gemini SynthID verdicts
|
||||
```
|
||||
|
||||
[`image-watermark-examples.csv`](image-watermark-examples.csv) and
|
||||
[`video-watermark-examples.csv`](video-watermark-examples.csv) are the coverage
|
||||
indexes for real carriers. They point to each canonical binary instead of
|
||||
duplicating it and record unsupported gaps and source-specific licensing.
|
||||
|
||||
## Storage rules
|
||||
|
||||
Large local-only research data (the 211 GB Spaces corpus and the frozen
|
||||
|
||||
@@ -3,6 +3,151 @@
|
||||
These files exercise real container, metadata, and pixel-provenance formats.
|
||||
They are test inputs, not evaluation corpora.
|
||||
|
||||
## OpenRouter metadata survey
|
||||
|
||||
The following files are original byte streams returned by OpenRouter's Image
|
||||
API on 2026-09-02. Each request used a repository-maintainer account, the same
|
||||
neutral still-life prompt, one 1:1 output, and no image reference. The prompt
|
||||
was `A documentary photograph of three smooth river stones on pale linen beside
|
||||
a small blue glass vase, soft natural daylight, plain uncluttered background,
|
||||
no text, no logos`.
|
||||
|
||||
| File | Model | Cost | SHA-256 | Expected metadata result |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `recraft-v3.webp` | `recraft/recraft-v3` | USD 0.04 | `e94c99ab50410092dbb601c8269ce812879e2271e18c7880021d2118666542ae` | Valid C2PA; `recraft.ai`; `trainedAlgorithmicMedia` |
|
||||
| `krea-2-medium-turbo.png` | `krea/krea-2-medium-turbo` | USD 0.015 | `ee1302c01e8da8e316e6563b0f9d36d511b9048fb2f70b8851eeeda98c5fb6a0` | No locally readable provenance |
|
||||
|
||||
Both were paid API generations. Recraft grants ownership for paid-plan output,
|
||||
and Krea states that users own compliant outputs. They are distributed under
|
||||
the repository license.
|
||||
|
||||
- Recraft terms: <https://www.recraft.ai/docs/plans-and-billing/commercial-rights-and-ownership>
|
||||
- Krea terms: <https://www.krea.ai/krea-2-licensing>
|
||||
|
||||
The same survey generated `sourceful/riverflow-v2-fast` output and found no
|
||||
locally readable metadata. It is not committed because Riverflow's terms
|
||||
restrict redistribution and using results to test or improve machine-learning
|
||||
systems. Its measured SHA-256 was
|
||||
`d4d7e80a3ed450129a0e77bdf330a83eb7de1e287d5b2b737cd26a011194a270`;
|
||||
OpenRouter recorded a USD 0.02 request cost.
|
||||
|
||||
## WaveSpeedAI metadata survey
|
||||
|
||||
The following measurements came from original byte streams returned by the
|
||||
WaveSpeedAI API on 2026-09-03. Each request used a repository-maintainer
|
||||
account and the same neutral still-life prompt recorded above. The account
|
||||
balance moved from USD 12.00 to USD 11.82 for the four successful requests.
|
||||
|
||||
| File | WaveSpeedAI model | SHA-256 | Expected metadata result |
|
||||
| --- | --- | --- | --- |
|
||||
| `qwen-image.png` | `wavespeed-ai/qwen-image/text-to-image` | `5b6d832834397498d0587b9b2536f88c75e923195c43c2b71d9f7f3c5422b4f1` | No provenance signal; one non-provenance PNG `job-id` text field |
|
||||
| `hunyuan-image-3.png` | `wavespeed-ai/hunyuan-image-3` | `6ae2ac073ac79b02b0934c905364f200420c2ff60fea232bd9e0a5fca785cc09` | Valid C2PA from `fal.ai` naming `fal-ai/hunyuan-image`, plus Adobe TrustMark Variant P, schema 0 |
|
||||
| `kling-image-v3.png` | `kwaivgi/kling-image-v3/text-to-image` | `501ab865b47ba59b64bc0f68118300744b0d5c7be2fa4e2ecbb3a78de5d8a82b` | TC260 PNG `AIGC` field naming producer `001191110108335469089C10100`; no visible Kling mark |
|
||||
| `seedream-v4.jpg` | `bytedance/seedream-v4` | `9ec6af1fc0509d74e264b9631a6cddd2ce7ce20146347fe418e9306032beb759` | No locally readable provenance |
|
||||
|
||||
All four original byte streams are committed. Section 11.1 of WaveSpeedAI's
|
||||
terms assigns its rights in Customer Data, explicitly including Outputs, to the
|
||||
customer. The live catalog records used for these requests expose no additional
|
||||
license, terms URL, attribution requirement, territory restriction, or
|
||||
commercial-use restriction. The maintainer therefore distributes these paid,
|
||||
neutral-prompt outputs under the repository license. This conclusion applies
|
||||
to these WaveSpeedAI API transactions; it does not import unrelated terms from
|
||||
the vendors' direct consumer services.
|
||||
|
||||
- WaveSpeedAI terms: <https://wavespeed.ai/static/terms>
|
||||
- WaveSpeedAI commercial-use policy: <https://wavespeed.ai/docs/commercial-use-policy>
|
||||
- Qwen-Image license: <https://github.com/QwenLM/Qwen-Image/blob/main/LICENSE>
|
||||
|
||||
## Qwen Create consumer output
|
||||
|
||||
`qwen-create-qwen-image-2.png` is the original 2048 x 2048 PNG downloaded from
|
||||
an authenticated Qwen Create generation on 2026-09-03. It was generated by
|
||||
`Qwen-Image 2.0` at 1:1 using the neutral still-life prompt recorded above.
|
||||
The current global consumer surface differs from the supported Chinese Qwen
|
||||
text mark: it places a small Qwen symbol at the bottom right, not
|
||||
`千问AI生成`. The existing Qwen text detector therefore correctly does not
|
||||
claim this new shape (measured strict confidence 0.178).
|
||||
|
||||
- SHA-256: `60c39ed8aedb081193c62289be549785e74d31fc8d071961003fabd74712429d`
|
||||
- Expected metadata signal: TC260 AIGC label
|
||||
- Expected `ContentProducer`: `001191440101MA9Y9T4H7A00000`
|
||||
- Expected visible result: no registered visible mark; the Qwen symbol is a
|
||||
newly observed, currently unsupported variant
|
||||
- License: repository license; generated and explicitly cleared by the
|
||||
maintainer
|
||||
- Qwen Create terms: <https://terms.alicdn.com/legal-agreement/terms/c_end_product_protocol/20260519200335649/20260519200335649.html>
|
||||
|
||||
## Open DWT-DCT
|
||||
|
||||
`sdxl-dwt-dct.png` is a real AI-generated carrier with the public 48-bit SDXL
|
||||
watermark embedded by ShieldMnt's `invisible-watermark` encoder using its
|
||||
`dwtDct` method. The carrier is the original `kling-image-v3.png` WaveSpeedAI
|
||||
output documented above, not a procedurally generated test texture. Encoding
|
||||
was lossless to PNG and removed the source container metadata; the resulting
|
||||
fixture contains only the expected open DWT-DCT signal.
|
||||
|
||||
- Source carrier SHA-256: `501ab865b47ba59b64bc0f68118300744b0d5c7be2fa4e2ecbb3a78de5d8a82b`
|
||||
- Fixture SHA-256: `9ec3dcbfea19e4651b898f98ada28a1c81f054d63621a0bba2d484aa77da251a`
|
||||
- Payload: `0b101100111110110010010000011110111011000110011110`
|
||||
- Expected signal: open DWT-DCT, `Stable Diffusion XL`
|
||||
- Verification: 48/48 payload bits recovered by both the upstream decoder and
|
||||
the in-tree decoder; `identify` reports the expected high-confidence signal
|
||||
- Encoder: <https://github.com/ShieldMnt/invisible-watermark>
|
||||
- License: repository license; the encoder is MIT-licensed
|
||||
|
||||
## Microsoft InvisMark
|
||||
|
||||
### Microsoft Paint
|
||||
|
||||
`microsoft-paint-invismark.png` is the original byte stream supplied directly
|
||||
by Xusheng Li on 2026-09-02 after his reverse-engineering research documented
|
||||
Paint's pixel watermark and its matching C2PA soft binding. He authorized public
|
||||
redistribution of the fixture under the MIT license. The neutral image was
|
||||
generated by Microsoft Paint from the prompt `a cobalt blue circle above a tiny
|
||||
orange square`.
|
||||
|
||||
- Source research: <https://xusheng.dev/posts/reversing/mspaint_invisible_watermark/main/>
|
||||
- SHA-256: `74eda22d210d534fcb5b75bedf8acd3bd110b48a95f4b9e546cd34f546effc05`
|
||||
- Dimensions: 1254 x 1254 RGB PNG
|
||||
- Expected signal: C2PA soft binding `com.microsoft.invismark.1`
|
||||
- Expected watermark ID: `a4ed421e-7c37-4409-998e-f8788c564572`
|
||||
- Expected platform: `Microsoft (Copilot / Designer)`
|
||||
- Expected C2PA result: valid asset binding and signature
|
||||
- License: MIT, reproduced in `../licenses/xusheng-li-paint-invismark-MIT.txt`
|
||||
|
||||
### Microsoft MAI-Image through OpenRouter
|
||||
|
||||
`microsoft-invismark.png` is the original byte stream returned by OpenRouter's
|
||||
Image API for `microsoft/mai-image-2.5-pro` on 2026-09-02. The request used a
|
||||
repository-maintainer account and asked for one 1:1 image. OpenRouter routed
|
||||
the request to Microsoft Azure. Microsoft states that it does not claim
|
||||
ownership of AI-service output; the maintainer distributes this output under
|
||||
the repository license.
|
||||
|
||||
- SHA-256: `be27ac7c351e7f381dc69e140ca3611ecd9db81e40926c68050ceffdd0ce6c04`
|
||||
- Expected signal: C2PA soft binding `com.microsoft.invismark.1`
|
||||
- Expected watermark ID: `19b070a1-23f0-40eb-826c-cade306337eb`
|
||||
- Expected platform: `Microsoft (Copilot / Designer)`
|
||||
- Request cost recorded by OpenRouter: USD 0.110757
|
||||
- License: repository license
|
||||
- Terms: <https://www.microsoft.com/en/servicesagreement/>
|
||||
|
||||
### Microsoft MAI-Image through Bing Image Creator
|
||||
|
||||
`microsoft-bing-image-creator.jpg` is the original download produced without
|
||||
sign-in by Microsoft's public Bing Image Creator on 2026-09-03. The page named
|
||||
the model `MAI-Image-2.5-Flash`; it used the neutral still-life prompt recorded
|
||||
above and the 3:2 aspect ratio. The downloaded image has no visible AI badge,
|
||||
so it does not close the separate visible Microsoft-badge fixture request.
|
||||
|
||||
- SHA-256: `55cad5355b6eeeb25f84ea074f85c0ea55b82d63c27f43e3429bb75f28734ac7`
|
||||
- Dimensions: 1248 x 832 RGB JPEG
|
||||
- Expected signal: valid C2PA plus soft binding `com.microsoft.invismark.1`
|
||||
- Expected watermark ID: `aec9a34e-665f-4549-9c02-9d29337a5de6`
|
||||
- Expected platform: `Microsoft (Copilot / Designer)`
|
||||
- License: repository license
|
||||
- Terms: <https://www.microsoft.com/en/servicesagreement/>
|
||||
|
||||
## Adobe TrustMark
|
||||
|
||||
`adobe-trustmark-p.png` is Adobe's official `images/ghost_P.png` Variant P
|
||||
|
||||
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 343 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 6.5 MiB |
|
After Width: | Height: | Size: 892 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 955 KiB |
@@ -17,6 +17,154 @@ The examples demonstrate DETECTION geometry and house style, not vendor raster
|
||||
fidelity; real-world variants (fonts, opacities, sizes) are covered by the
|
||||
engines' recorded calibration evidence.
|
||||
|
||||
The Qwen, Kling, Yuanbao, Baidu, Jimeng, LiblibAI, Microsoft, Sora, Hailuo, and Veo
|
||||
directories additionally contain real provider-marked sources. These files
|
||||
retain the source bytes and names used here are deliberately distinct from the
|
||||
generated canonical examples. The current LiblibAI output is evidence of a
|
||||
provider format change, not a positive example for the registered historical
|
||||
wordmark detector:
|
||||
|
||||
| File | Source | SHA-256 | Expected detector |
|
||||
| --- | --- | --- | --- |
|
||||
| `qwen/provider-original.png` | OpenNoMark `examples/qwen/image_324855086256596.png`, commit `9455d2d` | `dce9e17c9b9b0483c672b71183b6eb5562f8205bb39a6da14451e07db13b1a50` | Qwen, confidence 0.73 |
|
||||
| `kling/provider-original-direct.png` | Authenticated Kling AI IMAGE 3.0 generation, downloaded 2026-09-04 | `aefbf69a99cf7eb4211cc0513c6979b81731107a1bc605c972e01900b7c56f51` | Kling, confidence 0.43 |
|
||||
| `yuanbao/provider-original.png` | Authenticated Tencent Yuanbao AI Image generation, downloaded 2026-09-05 | `e4fd856565d0434ef06deb78ff2088e597c4fec98640ad737213c7c0a917c82d` | Yuanbao, confidence 0.49 |
|
||||
| `baidu/provider-original.jpeg` | OpenNoMark `examples/baidu/baidu_01.jpeg`, commit `9455d2d` | `52852c528f1a7b8918b665b2fcf883737ecc5016481d9c7683ebe07e152cc9d2` | Baidu, confidence 0.66 |
|
||||
| `jimeng_pill/provider-published-example.jpg` | JPEG embedded on page 29 of Zhonglun W&D's 2026 *Bank Finance Legal Newsletter* | `1182fba74d3753785345f8a35d09a8c9b52ea8383ebe9ee999d0d027437f03fd` | Jimeng AI pill, confidence 0.28; Jimeng wordmark, confidence 0.61 |
|
||||
| `liblib/current-provider-output.png` | Authenticated LiblibAI Smart Image V2 generation, downloaded 2026-09-05 | `60398d4f06fd50e047d3321c62405dae0a1c4a7070e77ac5e0548c516257d2e3` | No `liblib` detection: current top-left `AI生成` pill differs from the registered bottom-center `LiblibAI` wordmark |
|
||||
| `microsoft/provider-original.png` | Authenticated Microsoft Copilot generation, downloaded 2026-09-03 | `0e76fb8aa0540b18fee4d63ac4b5fd63c7eee310474e896d21d27e668403afe7` | Microsoft, confidence 0.54 |
|
||||
| `sora/provider-frame.jpg` | Sora 2 video frame from LLinked's Apache-2.0 `sora-watermark-dataset` | `bbcf70b737c30568668572a5bb23e70c52c9687808b0714ca98f9fac073f12c4` | Sora frame localization, confidence 0.69 |
|
||||
| `sora/provider-original.mp4` | LLinked's Apache-2.0 `SoraWatermarkCleaner` fixture `resources/puppies.mp4`, commit `ad35ce9` | `7dd8a9d43d43cd5b901946c7ba14e8018e18d47e75f0f774157327ba7e9181c5` | Sora, 300/300 stable frames; Sora C2PA claim |
|
||||
| `hailuo/provider-original.mp4` | Authenticated Hailuo AI MiniMax H3 generation, downloaded with `With Watermark` selected on 2026-09-03 | `6152609e0339c443af79e244440e1b1050f3c615a50f76bfaf6146584e68142f` | Hailuo, 124/124 stable frames |
|
||||
| `kling/provider-original.mp4` | Authenticated Kling AI VIDEO 3.0 generation, downloaded 2026-09-04 | `f3e8d6a765fca699036d68fde28eb16f7aed97b6702f06f318e61ae8d4e53a69` | Kling, 121/121 stable frames |
|
||||
| `veo/provider-original.mp4` | Authenticated Google Flow Veo 3.1 Fast generation with `Visible watermarking` enabled, downloaded 2026-09-03 | `e778194b545e34dafd2d5be58691031a070862890c41e6c527a652a114a7c7a4` | Veo, 192/192 stable frames |
|
||||
|
||||
OpenNoMark describes its corpus as real-image examples and distributes the
|
||||
repository under CC BY-NC-SA 4.0. Its license text is reproduced in
|
||||
`../../licenses/open-no-mark-CC-BY-NC-SA-4.0.txt`. The upstream repository does
|
||||
not record per-image authorship beyond that repository-level license and claim.
|
||||
The Qwen and Baidu files remain under that license and are not offered under
|
||||
this repository's Apache-2.0 license.
|
||||
|
||||
The Microsoft file is the original 1024 x 1024 PNG downloaded from an
|
||||
authenticated Copilot image-generation conversation. It uses the neutral
|
||||
still-life prompt recorded in `../README.md`, carries the visible top-right
|
||||
`Made with AI` pill, valid Microsoft C2PA, and InvisMark soft-binding ID
|
||||
`975290d4-9c2f-4359-ad5a-92c5b5b850a4`. Microsoft does not claim ownership of
|
||||
AI-service output; the maintainer distributes this generated output under the
|
||||
repository license.
|
||||
|
||||
The Sora frame is the original JPEG frame
|
||||
`images/train/images/failed_image_000016_frame_000150.jpg` from LLinked's
|
||||
`sora-watermark-dataset`. The dataset card describes its images as frames
|
||||
extracted from Sora-generated videos, provides manual watermark boxes, and
|
||||
licenses the dataset under Apache-2.0. This neutral CGI frame carries the
|
||||
current moving mascot-and-wordmark raster and passes the in-tree frame
|
||||
localizer.
|
||||
|
||||
The Sora MP4 is the byte-for-byte `resources/puppies.mp4` fixture tracked by
|
||||
LLinked's Apache-2.0 `SoraWatermarkCleaner` at commit `ad35ce9`. It preserves
|
||||
the moving mascot-and-wordmark raster, timing, audio, and the source C2PA
|
||||
manifest. The in-tree video path detects Sora on all 300 frames. The C2PA claim
|
||||
names Sora as the generator and OpenAI/Truepic as the issuer; its content
|
||||
integrity and signature verify, while the reader reports the signer certificate
|
||||
as expired and untrusted.
|
||||
|
||||
- Sora watermark dataset:
|
||||
<https://huggingface.co/datasets/LLinked/sora-watermark-dataset>
|
||||
- SoraWatermarkCleaner source fixture:
|
||||
<https://github.com/linkedlist771/SoraWatermarkCleaner/blob/ad35ce99a34fc9f9f6d448537e0c348311e74ccd/resources/puppies.mp4>
|
||||
|
||||
The Hailuo file is the original 2944 x 1248, 5-second MP4 downloaded from an
|
||||
authenticated Hailuo AI generation. It was generated with MiniMax H3 for 60
|
||||
top-up credits from the neutral prompt `A blue ceramic mug slowly rotates on a
|
||||
plain light gray studio table, soft even lighting, fixed camera, clean
|
||||
background.` The download menu explicitly offered clean and `With Watermark`
|
||||
variants; this fixture is the latter. It carries the visible lower-right
|
||||
`MINIMAX | hailuo AI` composite and a TC260 AIGC label naming MiniMax as the
|
||||
producer. The maintainer generated and explicitly cleared this output for use
|
||||
under the repository license.
|
||||
|
||||
- Hailuo AI paid-service and credit terms:
|
||||
<https://hailuoai.video/doc/payment-policy.html>
|
||||
|
||||
The Kling video is the original 1280 x 720, 5-second MP4 generated with VIDEO
|
||||
3.0 for 30 credits at 720p without native audio. Its neutral prompt was `A
|
||||
locked-off wide shot of a small white paper boat floating across a calm
|
||||
dark-blue pond at dusk, gentle ripples, realistic cinematic lighting, no text,
|
||||
no logos.` It carries the fixed lower-right `KlingAI 3.0` logo and no locally
|
||||
readable provenance metadata. The maintainer generated and explicitly cleared
|
||||
the output for this noncommercial deterministic computer-vision regression
|
||||
fixture. Kling AI's terms say the user owns applicable rights in the output,
|
||||
require a regular account to retain Kling branding when distributing it, and
|
||||
prohibit commercial use without written permission. The fixture retains the
|
||||
brand and remains subject to those terms; it is not offered under the
|
||||
repository license.
|
||||
|
||||
- Kling AI terms of service: <https://kling.ai/docs/user-policy>
|
||||
- Kling AI paid-service terms: <https://kling.ai/docs/payment-policy>
|
||||
|
||||
The direct Kling image is the original 1024 x 1024 RGB PNG generated with
|
||||
IMAGE 3.0 in 1K SD mode for one credit. Its neutral prompt was `A documentary
|
||||
photograph of three smooth river stones on pale linen beside a small blue glass
|
||||
vase, soft natural daylight, plain uncluttered background, no text, no logos.`
|
||||
It carries the current lower-right `KlingAI 3.0` mark and a TC260 AIGC field
|
||||
whose producer code `001191110108335469089C10100` normalizes to Kuaishou's
|
||||
registered USCC. The maintainer generated and explicitly cleared the output for
|
||||
this noncommercial deterministic computer-vision regression fixture. The same
|
||||
Kling terms and retained-brand restriction listed for the video apply; the file
|
||||
is not offered under the repository license.
|
||||
|
||||
The Yuanbao image is the original 1776 x 1328 RGB PNG returned by an
|
||||
authenticated AI Image conversation. It was generated at no charge from the
|
||||
neutral prompt `A documentary photograph of a blue ceramic mug on a plain
|
||||
light-gray studio table, soft even lighting, no text, no logos, no people.` It
|
||||
carries the visible lower-right two-line `元宝` / `AI生成` mark and a TC260 AIGC
|
||||
field naming Tencent's registered producer. The maintainer generated and
|
||||
explicitly cleared this output for use under the repository license.
|
||||
|
||||
The Jimeng image is the byte-for-byte embedded JPEG extracted with
|
||||
`pdfimages` from page 29 of Zhonglun W&D's publicly distributed 2026 *Bank
|
||||
Finance Legal Newsletter*. It is a real Jimeng-generated debt-collection
|
||||
poster carrying both the top-left `AI生成` pill and the lower-right `即梦AI`
|
||||
wordmark. The repository retains one 705 x 705 image rather than the complete
|
||||
33-page publication, solely to test identification and removal of the two
|
||||
marks. Copyright remains with the source rights holders; this research fixture
|
||||
is not licensed under Apache-2.0. See
|
||||
`../../licenses/zhonglunwende-jimeng-fair-use.txt` for provenance and use
|
||||
limitations.
|
||||
|
||||
- Zhonglun W&D source publication:
|
||||
<https://www.zhonglunwende.com/uploads/20260202/97f9a8f64892eac6b7e04e5e7ea45d0e.pdf>
|
||||
|
||||
The LiblibAI image is the original 2048 x 2048 RGBA PNG generated with Smart
|
||||
Image V2 for 18 introductory points from the same neutral prompt. It carries a
|
||||
top-left `AI生成` pill and a TC260 AIGC field whose producer code contains
|
||||
LiblibAI's registered USCC, but it does not carry the historical bottom-center
|
||||
`LiblibAI` wordmark that the registered `liblib` engine detects. This file
|
||||
therefore records the current provider behavior without falsely closing the
|
||||
historical positive-example gap. The maintainer generated and explicitly
|
||||
cleared the output for use under the repository license.
|
||||
|
||||
- LiblibAI user agreement (generated-output ownership and watermark choices):
|
||||
<https://www.liblib.art/activities/468ad794ccc7408d81757fd91be003ec?hideHeader=1>
|
||||
|
||||
The Veo file is the original 1280 x 720, 8-second MP4 downloaded from an
|
||||
authenticated Google Flow project. It was generated with Veo 3.1 Fast for 20
|
||||
Flow credits from the neutral prompt `A blue mug rotates on gray. Static camera.
|
||||
No people, text, logos, or audio.` after the account's `Visible watermarking`
|
||||
setting was enabled. It carries the fixed, low-contrast `Veo` text at the bottom
|
||||
right, valid Google C2PA, and an invisible SynthID marker. Google documents that
|
||||
Flow clips can be downloaded and shared, states that Google does not claim
|
||||
ownership of original generated content, and explicitly identifies SynthID in
|
||||
all Flow video output. The maintainer distributes this generated output under
|
||||
the repository license.
|
||||
|
||||
- Google Flow output and watermark documentation:
|
||||
<https://support.google.com/flow/answer/16353333>
|
||||
- Google Flow download and sharing documentation:
|
||||
<https://support.google.com/flow/answer/16935308>
|
||||
|
||||
## Regeneration
|
||||
|
||||
uv run python scripts/render_visible_examples.py
|
||||
@@ -27,12 +175,14 @@ detect on its own example, so regeneration is the fix point for drift.
|
||||
## Layout
|
||||
|
||||
<mark-key>/example.png 1536x2048..2048x2048 PNG, one per image mark
|
||||
<mark-key>/provider-original.*
|
||||
Documented real provider-marked source where available
|
||||
<mark-key>/example.mp4 960x540 90-frame clip, one per video mark
|
||||
(kling carries both: it is registered in both registries)
|
||||
|
||||
Special cases: `gemini` composites the sparkle alpha map at the provider's
|
||||
configured position; `jimeng_pill` is the capture-less pill at the measured
|
||||
3:4 portrait geometry; `microsoft` is the opaque white pill with dark text
|
||||
configured position; `jimeng_pill` uses the measured 3:4 portrait geometry;
|
||||
`microsoft` is the opaque white pill with dark text
|
||||
holes (the discriminator its detector keys on). Video examples composite the
|
||||
detector's own synthetic template on every frame; where two marks share a
|
||||
shape family the example carries the discriminative variant (`veo` the legacy
|
||||
|
||||
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 6.9 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 2.2 MiB |
@@ -0,0 +1,19 @@
|
||||
key,provider,watermark_type,path,status,verification,license
|
||||
gemini,Google Gemini,visible sparkle,data/calibration/gemini/gemini_black_2048.png,available,original provider capture and detector calibration,repository
|
||||
doubao,ByteDance Doubao,visible text,data/calibration/doubao/doubao_gray_1x1_1.png,available,original provider capture and detector calibration,repository
|
||||
jimeng,ByteDance Jimeng,visible wordmark,data/calibration/jimeng/jimeng_cap_C.png,available,original provider capture and detector calibration,repository
|
||||
qwen,Alibaba Qwen consumer app,visible text,data/fixtures/visible/qwen/provider-original.png,available,detected by Qwen engine; distributed under the OpenNoMark repository's CC BY-NC-SA 4.0 license; current global Qwen Create uses a different symbol captured in provenance fixtures,CC-BY-NC-SA-4.0; excluded from Apache-2.0
|
||||
kling,Kuaishou Kling AI,visible text,data/fixtures/visible/kling/provider-original-direct.png,available,authenticated Kling IMAGE 3.0 original; Latin KlingAI 3.0 mark detected at confidence 0.43; TC260 producer maps to Kuaishou,subject to Kling AI terms; noncommercial fixture
|
||||
yuanbao,Tencent Yuanbao,visible two-line text,data/fixtures/visible/yuanbao/provider-original.png,available,authenticated Yuanbao original; detected by Yuanbao engine at confidence 0.49; TC260 producer metadata maps to Tencent,repository
|
||||
samsung,Samsung Galaxy AI,visible Italian text,data/calibration/samsung/samsung_gray_1.png,available,original provider capture and detector calibration,repository
|
||||
runninghub,RunningHub,visible text,,missing,no redistributable provider original found,
|
||||
baidu,Baidu,visible text and tag,data/fixtures/visible/baidu/provider-original.jpeg,available,detected by Baidu engine; distributed under the OpenNoMark repository's CC BY-NC-SA 4.0 license,CC-BY-NC-SA-4.0; excluded from Apache-2.0
|
||||
liblib,LiblibAI,visible wordmark,data/fixtures/visible/liblib/current-provider-output.png,partial,"authenticated current LiblibAI original carries a top-left AI生成 pill rather than the registered historical bottom-center LiblibAI wordmark; TC260 producer metadata maps to LiblibAI; historical positive remains missing",repository
|
||||
microsoft,Microsoft image output,visible top-right AI badge,data/fixtures/visible/microsoft/provider-original.png,available,authenticated Copilot original detected by Microsoft engine at confidence 0.54; also has valid C2PA and InvisMark,repository
|
||||
jimeng_pill,ByteDance Jimeng,visible AI pill,data/fixtures/visible/jimeng_pill/provider-published-example.jpg,available,"real Jimeng output embedded in page 29 of Zhonglun W&D's 2026 Bank Finance Legal Newsletter; direct jimeng_pill detection confidence 0.28; the same image also carries the Jimeng wordmark",fair-use research fixture; excluded from Apache-2.0
|
||||
google_synthid,Google,image SynthID,data/synthid/originals/Gemini_Generated_Image_633uuy633uuy633u.png,available,provider oracle recorded in data/synthid/manifest.csv,repository
|
||||
openai_synthid,OpenAI,image SynthID,"data/synthid/originals/ChatGPT Image May 30, 2026, 10_31_08 AM.png",available,provider oracle recorded in data/synthid/manifest.csv,repository
|
||||
meta_content_seal,Meta Muse Image,image Content Seal,data/contentseal/originals/gen_fox_forest.webp,available,provider oracle recorded in data/contentseal/manifest.csv,repository
|
||||
microsoft_invismark,Microsoft Paint,image InvisMark,data/fixtures/provenance/microsoft-paint-invismark.png,available,"original Paint output supplied by Xusheng Li; valid C2PA names com.microsoft.invismark.1 and watermark ID a4ed421e-7c37-4409-998e-f8788c564572",MIT
|
||||
open_dwt_dct,Stable Diffusion / SDXL / FLUX workflows,open DWT-DCT,data/fixtures/provenance/sdxl-dwt-dct.png,available,real AI-generated carrier with the official SDXL payload recovered 48/48 by upstream and in-tree decoders,repository
|
||||
adobe_trustmark_p,Adobe,image TrustMark Variant P,data/fixtures/provenance/adobe-trustmark-p.png,available,official Adobe example and expected schema recorded in data/fixtures/README.md,MIT
|
||||
|
@@ -0,0 +1,439 @@
|
||||
Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
Public License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
||||
("Public License"). To the extent this Public License may be
|
||||
interpreted as a contract, You are granted the Licensed Rights in
|
||||
consideration of Your acceptance of these terms and conditions, and the
|
||||
Licensor grants You such rights in consideration of benefits the
|
||||
Licensor receives from making the Licensed Material available under
|
||||
these terms and conditions.
|
||||
|
||||
|
||||
Section 1 -- Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
|
||||
c. BY-NC-SA Compatible License means a license listed at
|
||||
creativecommons.org/compatiblelicenses, approved by Creative
|
||||
Commons as essentially the equivalent of this Public License.
|
||||
|
||||
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
|
||||
e. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
|
||||
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
|
||||
g. License Elements means the license attributes listed in the name
|
||||
of a Creative Commons Public License. The License Elements of this
|
||||
Public License are Attribution, NonCommercial, and ShareAlike.
|
||||
|
||||
h. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
|
||||
i. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
|
||||
k. NonCommercial means not primarily intended for or directed towards
|
||||
commercial advantage or monetary compensation. For purposes of
|
||||
this Public License, the exchange of the Licensed Material for
|
||||
other material subject to Copyright and Similar Rights by digital
|
||||
file-sharing or similar means is NonCommercial provided there is
|
||||
no payment of monetary compensation in connection with the
|
||||
exchange.
|
||||
|
||||
l. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
|
||||
m. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
|
||||
n. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
|
||||
|
||||
Section 2 -- Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part, for NonCommercial purposes only; and
|
||||
|
||||
b. produce, reproduce, and Share Adapted Material for
|
||||
NonCommercial purposes only.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
|
||||
b. Additional offer from the Licensor -- Adapted Material.
|
||||
Every recipient of Adapted Material from You
|
||||
automatically receives an offer from the Licensor to
|
||||
exercise the Licensed Rights in the Adapted Material
|
||||
under the terms and conditions of the Adapter's License
|
||||
You apply.
|
||||
|
||||
c. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties, including when
|
||||
the Licensed Material is used other than for NonCommercial
|
||||
purposes.
|
||||
|
||||
|
||||
Section 3 -- License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
|
||||
b. ShareAlike.
|
||||
|
||||
In addition to the conditions in Section 3(a), if You Share
|
||||
Adapted Material You produce, the following conditions also apply.
|
||||
|
||||
1. The Adapter's License You apply must be a Creative Commons
|
||||
license with the same License Elements, this version or
|
||||
later, or a BY-NC-SA Compatible License.
|
||||
|
||||
2. You must include the text of, or the URI or hyperlink to, the
|
||||
Adapter's License You apply. You may satisfy this condition
|
||||
in any reasonable manner based on the medium, means, and
|
||||
context in which You Share Adapted Material.
|
||||
|
||||
3. You may not offer or impose any additional or different terms
|
||||
or conditions on, or apply any Effective Technological
|
||||
Measures to, Adapted Material that restrict exercise of the
|
||||
rights granted under the Adapter's License You apply.
|
||||
|
||||
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of databases for NonCommercial purposes
|
||||
only;
|
||||
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material,
|
||||
including for purposes of Section 3(b); and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
|
||||
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
|
||||
|
||||
Section 6 -- Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
|
||||
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
|
||||
|
||||
Section 8 -- Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Xusheng Li
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,22 @@
|
||||
Jimeng published-image research fixture
|
||||
=======================================
|
||||
|
||||
File:
|
||||
data/fixtures/visible/jimeng_pill/provider-published-example.jpg
|
||||
|
||||
Source:
|
||||
Zhonglun W&D, Bank Finance Legal Newsletter, 2026, page 29
|
||||
https://www.zhonglunwende.com/uploads/20260202/97f9a8f64892eac6b7e04e5e7ea45d0e.pdf
|
||||
|
||||
Extraction:
|
||||
The file is the JPEG image embedded in the source PDF, extracted byte-for-byte
|
||||
with pdfimages. SHA-256:
|
||||
1182fba74d3753785345f8a35d09a8c9b52ea8383ebe9ee999d0d027437f03fd
|
||||
|
||||
Use in this repository:
|
||||
This single image is retained as a minimal research and interoperability
|
||||
fixture for identifying and removing the visible Jimeng AI-generation marks.
|
||||
It is not offered under this repository's Apache-2.0 license. Copyright and
|
||||
all other rights remain with their respective holders. No license for uses
|
||||
outside the repository's research, testing, criticism, and documentation is
|
||||
granted here.
|
||||
@@ -0,0 +1,8 @@
|
||||
key,provider,watermark_type,path,status,verification,license
|
||||
sora,OpenAI Sora,visible moving mascot and wordmark,data/fixtures/visible/sora/provider-original.mp4,available,"Apache-2.0 upstream original; detected by Sora engine on 300/300 frames; C2PA claim names Sora and OpenAI/Truepic, with valid integrity and signature but an expired untrusted signer certificate",Apache-2.0
|
||||
veo,Google Veo,visible fixed text,data/fixtures/visible/veo/provider-original.mp4,available,"authenticated Google Flow Veo 3.1 Fast original; detected by Veo engine on 192/192 frames; valid C2PA and provider-confirmed SynthID",repository
|
||||
seedance,ByteDance Seedance,visible boxed AI label,,missing,"OpenRouter Seedance 2.0 Mini with watermark=true produced BytePlus C2PA but no visible boxed AI label; direct consumer original still needed",
|
||||
doubao,ByteDance Doubao,visible fixed text,,missing,no redistributable provider original found,
|
||||
dola,ByteDance Dola,visible fixed text,,missing,no redistributable provider original found,
|
||||
hailuo,MiniMax Hailuo AI,visible composite label,data/fixtures/visible/hailuo/provider-original.mp4,available,"authenticated Hailuo AI MiniMax H3 original downloaded with With Watermark selected; detected by Hailuo engine on 124/124 frames; TC260 AIGC label names MiniMax",repository
|
||||
kling,Kuaishou Kling AI,visible fixed logo and wordmark,data/fixtures/visible/kling/provider-original.mp4,available,"authenticated Kling AI VIDEO 3.0 original; detected by Kling engine on 121/121 frames; no locally readable provenance metadata",Kling AI terms; noncommercial fixture
|
||||
|
@@ -112,8 +112,9 @@ one observed cross-source spread):
|
||||
Derived by the shipped rule: 0.08 + (0.08 - 0.04) = 0.12, rounded to the
|
||||
measured rung **0.125**, which was then oracle-verified clean on both worst
|
||||
sources. Oracle: the public `ai.azure.com/nextgen/validate` page; its
|
||||
`Inconclusive` verdict is the site's watermark-negative, weaker than an
|
||||
API-level `Watermark: false`, the same caveat the qwen cohort carries.
|
||||
`Inconclusive` verdict is the site's clean outcome and provides the provider
|
||||
oracle used for this certification. The API exposes a more detailed report,
|
||||
not a different class of certification.
|
||||
|
||||
## Fidelity at the floors (scripts/fidelity_metrics.py)
|
||||
|
||||
|
||||
@@ -19,3 +19,8 @@ This page records notices required by source dependencies and licensed derivativ
|
||||
TrustMark Variant P example, licensed under MIT. Its source commit, digest,
|
||||
and reproduced license are recorded beside the fixture in
|
||||
`data/fixtures/README.md` and `data/licenses/adobe-trustmark-MIT.txt`.
|
||||
- `data/fixtures/provenance/microsoft-paint-invismark.png` is an original
|
||||
Microsoft Paint output supplied by Xusheng Li and licensed by him under MIT.
|
||||
Its source research, digest, expected signal, and reproduced license are
|
||||
recorded in `data/fixtures/README.md` and
|
||||
`data/licenses/xusheng-li-paint-invismark-MIT.txt`.
|
||||
@@ -373,9 +373,9 @@ supported AI provenance metadata without transcoding streams.
|
||||
`video visible` and `remove_video_visible` additionally support the moving
|
||||
Sora 2 mascot and wordmark, the current Veo four-point diamond, the legacy
|
||||
`Veo` text, the Seedance boxed `AI` label, the fixed `Dola AI` text, the Hailuo AI
|
||||
MINIMAX/Hailuo AI composite label, and the bottom-right Kling AI label with its
|
||||
version suffix. Detection requires a recurring visual candidate across
|
||||
adjacent frames. Fixed-mark candidates must remain anchored rather than
|
||||
MINIMAX/Hailuo AI composite label, and the bottom-right Kling AI `KLING AI` or
|
||||
`KlingAI` label with its version suffix. Detection requires a recurring visual
|
||||
candidate across adjacent frames. Fixed-mark candidates must remain anchored rather than
|
||||
drifting with a scene object. Kling AI also requires a bright low-saturation
|
||||
candidate near the expected frame edge. Provider provenance can recover
|
||||
low-contrast runs only after visual evidence exists for the marks that define a
|
||||
|
||||
@@ -333,7 +333,7 @@ synthetic silhouettes for the current four-point diamond and legacy `Veo`
|
||||
text. Seedance uses a synthetic rounded boxed-`AI` silhouette, while Dola uses
|
||||
an OpenCV-font `Dola AI` silhouette. Hailuo AI uses a synthetic waveform,
|
||||
MINIMAX/Hailuo AI text, separator, and ring. Kling AI combines synthetic font
|
||||
variants with a ring approximation of its swirl; the logo path rescues
|
||||
and capitalization variants with a ring approximation of its swirl; the logo path rescues
|
||||
wordmarks whose version or font differs, while the edge and white-label gates
|
||||
reject recurring scene texture. All fixed-mark searches are bounded to the
|
||||
expected lower-frame area and calibrated independently. A strong relocated Veo
|
||||
@@ -345,7 +345,7 @@ normalized representations across all detectors, and caches resized synthetic
|
||||
template features for the fixed stream geometry. Provider confidence scales
|
||||
are not comparable: selection applies each provider's temporal arbiter and
|
||||
takes the first stable result in specificity order (`sora`, `veo`, `seedance`,
|
||||
`dola`, `hailuo`, `kling`). An explicit mark uses the same scan path with one
|
||||
`doubao`, `dola`, `hailuo`, `kling`). An explicit mark uses the same scan path with one
|
||||
candidate. Removal also collects authoritative per-frame timestamps for the
|
||||
encoder, while identification omits that unused ffprobe pass.
|
||||
|
||||
@@ -1199,8 +1199,8 @@ the platform sentence `identify` reports for it, and the metadata signals that
|
||||
confirm its vendor. `identify._VISIBLE_MARK_PLATFORM` and the signal mapping in
|
||||
`api.visible_provenance` are derived from those rows rather than hand-maintained
|
||||
beside them, so registering a mark is one edit. Two marks carry no platform of
|
||||
their own: the Gemini sparkle has its own higher-confidence path, and the
|
||||
capture-less pill is too weak to attribute.
|
||||
their own: the Gemini sparkle has its own higher-confidence path, and the pill
|
||||
alone is too weak to attribute.
|
||||
|
||||
The set of marks that veto the pill is DERIVED from the registry rows: every mark
|
||||
under the same label regime (`tc260`) belonging to a different product. It used to
|
||||
@@ -1285,6 +1285,15 @@ be represented by the shared base:
|
||||
- [`liblib_engine.py`](../src/remove_ai_watermarks/liblib_engine.py)
|
||||
- [`microsoft_engine.py`](../src/remove_ai_watermarks/microsoft_engine.py)
|
||||
|
||||
Kling keeps two independently gated silhouettes under one registry key. The
|
||||
older measured cohort uses `可灵AI 3.0`; a direct authenticated IMAGE 3.0 export
|
||||
on 2026-09-04 uses `KlingAI 3.0`. The Latin template scored 0.429 on that 1024 x
|
||||
1024 provider original. Its narrow 0.9/1.0/1.1 scale ladder scored at most 0.349
|
||||
across the 94 available neighboring real and synthetic image controls, while an
|
||||
adversarial solid corner blob reached 0.379, so its strict gate is 0.40. This is
|
||||
one-positive provisional calibration, intentionally separate from the older
|
||||
CJK detector rather than presented as broad recall evidence.
|
||||
|
||||
The measured Microsoft badge variant (2026-08-27 registration) is the first
|
||||
`tr`-corner mark and the first `long`-side scale basis: the pill tracks the
|
||||
render dimension, so a
|
||||
@@ -1406,12 +1415,15 @@ correlate with textured corners, not with pills: the edge-NCC keys on "text-like
|
||||
structure top-left". As with the Jimeng wordmark's silhouette, no threshold repairs
|
||||
this; a bare arm needs a detector that keys on the pill's rounded-rectangle
|
||||
geometry, and until one exists the bare-arm question is settled by this
|
||||
measurement, not by gate tuning. Harness: `data/spaces/_pill_bare_measure.py`
|
||||
measurement, not by gate tuning. The local calibration harness is not tracked.
|
||||
(cohorts A/B/C over the no-signal pool).
|
||||
|
||||
The capture-less Jimeng pill lives in
|
||||
The weak Jimeng pill detector lives in
|
||||
[`pill_engine.py`](../src/remove_ai_watermarks/pill_engine.py). It uses a
|
||||
synthetic silhouette for detection and a fixed top-left footprint.
|
||||
synthetic silhouette for detection and a fixed top-left footprint. Its public,
|
||||
published real-world regression carrier is
|
||||
`data/fixtures/visible/jimeng_pill/provider-published-example.jpg`; the direct
|
||||
detector scores the pill at 0.28 and the same image's Jimeng wordmark at 0.61.
|
||||
|
||||
Each engine has a corresponding test module under [`tests/`](../tests/).
|
||||
Shared behavior is covered by:
|
||||
@@ -1434,10 +1446,10 @@ negative, so the bar stays at 0.35. Through the shipped arbiter
|
||||
(`identify_video`): 32/39 selected as doubao, 0/25 false; the remainder split
|
||||
between no stable run (5) and cross-template ties handed to earlier table
|
||||
entries (sora 1, kling 1) -- the registry's known order-decides behavior, not a
|
||||
doubao-specific defect. Harness: `data/spaces/_doubao_seq_measure.py`.
|
||||
doubao-specific defect. The local sequence-calibration harness is not tracked.
|
||||
|
||||
Two further video candidates were measured and PARKED the same day (2026-08-28,
|
||||
`data/spaces/_rh_jm_video_calibrate.py`): the Jimeng CN wordmark does not
|
||||
local RunningHub/Jimeng video calibration): the Jimeng CN wordmark does not
|
||||
separate on video (1/5 positives vs 2/25 negatives hold a 12-frame 0.35 run --
|
||||
the same silhouette-generality the image jimeng engine documents), and
|
||||
RunningHub video separates (1/2 positives, 0/25 negatives) but a two-positive
|
||||
|
||||
@@ -14,12 +14,12 @@ The `visible` command registers these mark keys:
|
||||
| `doubao` | `豆包AI生成` | Bottom right | Vendor specific text detector. |
|
||||
| `jimeng` | `★ 即梦AI` | Bottom right | Vendor specific text detector. |
|
||||
| `qwen` | `千问AI生成` | Bottom right | Strict visual gate. |
|
||||
| `kling` | `可灵AI 3.0` | Bottom right | Only calibrated variants are covered. |
|
||||
| `kling` | `可灵AI 3.0` or `KlingAI 3.0` | Bottom right | Separate calibrated silhouettes cover the older CJK and current IMAGE 3.0 Latin variants. |
|
||||
| `yuanbao` | `元宝` over `AI生成` | Bottom right | Standard two-line variant only. |
|
||||
| `samsung` | `✦ Contenuti generati dall'AI` | Bottom left | Calibrated for the Italian text variant. |
|
||||
| `runninghub` | `RunningHub AI生成` | Top left | Strict visual and position gates. |
|
||||
| `baidu` | `百度 AI生成` | Bottom right | Detector and extended removal footprint. |
|
||||
| `liblib` | `LiblibAI` | Bottom center | Includes a minimum image size gate. |
|
||||
| `liblib` | `LiblibAI` | Bottom center | Includes a minimum image size gate. A 2026-09-05 Smart Image V2 provider original instead carries a smaller top-left `AI生成` pill and is not detected by this historical-wordmark engine. |
|
||||
| `microsoft` | One Microsoft white AI-badge variant | Top right | Strict uses the visual gate; auto can use Microsoft provenance for the measured [relaxed gate](module-internals.md#visible-mark-removal). Other documented icon, text, and position variants are not covered. |
|
||||
| `jimeng_pill` | `AI生成` pill | Top left | Weak detector with additional product and background gates. |
|
||||
|
||||
@@ -30,9 +30,16 @@ the masked area.
|
||||
Marks from other vendors are not detected automatically. Use `erase --region`
|
||||
when you can select the affected area yourself.
|
||||
|
||||
Synthetic examples for every registered image and video mark live in the
|
||||
[visible-mark gallery](../data/fixtures/visible/README.md). They demonstrate the
|
||||
detectors' canonical geometry and house style, not vendor raster fidelity.
|
||||
Synthetic canonical examples for every registered image and video mark live in
|
||||
the [visible-mark gallery](../data/fixtures/visible/README.md), alongside
|
||||
documented real provider originals where redistribution is cleared. The
|
||||
canonical examples demonstrate detector geometry and house style; provider
|
||||
originals exercise vendor raster fidelity.
|
||||
|
||||
Provider formats can change independently of the registered key. In particular,
|
||||
the current LiblibAI sample in the gallery preserves a real new-format output
|
||||
and its LiblibAI TC260 producer metadata, but is deliberately not listed as a
|
||||
positive detector fixture.
|
||||
|
||||
### Visible video marks
|
||||
|
||||
@@ -44,12 +51,12 @@ detectors' canonical geometry and house style, not vendor raster fidelity.
|
||||
| `seedance` | Boxed `AI` label | Fixed bottom-right corner | Requires an anchored recurring match; the full localized box is filled because a thinner synthetic shape mask leaves the real translucent rim behind. |
|
||||
| `dola` | `Dola AI` text | Fixed bottom-right corner | Requires an anchored recurring match; ByteDance or BytePlus provenance can relax only an existing visual run. |
|
||||
| `hailuo` | `MINIMAX \| hailuo AI` composite label | Fixed lower edge | Uses a synthetic waveform, text, separator, and ring silhouette; the complete recurring label box is filled. A TC260 label naming MiniMax as producer can relax only an existing stable run. |
|
||||
| `kling` | Kling AI swirl, `KLING AI`, version, and optional `PRO` suffix | Fixed bottom-right edge | Combines a synthetic logo rescue with font variants, an edge gate, a white-label gate, and anchored temporal recurrence. |
|
||||
| `kling` | Kling AI swirl, `KLING AI` or `KlingAI`, version, and optional `PRO` suffix | Fixed bottom-right edge | Combines a synthetic logo rescue with font and capitalization variants, an edge gate, a white-label gate, and anchored temporal recurrence. |
|
||||
|
||||
`video identify`, `video visible`, and `video all` share this registry and the
|
||||
same temporal arbiter. It is separate from the image registry because selection
|
||||
is made over a sequence rather than one raster. The default `auto` mode scans
|
||||
all six entries in one decode pass and selects the first temporally stable
|
||||
all seven entries in one decode pass and selects the first temporally stable
|
||||
match in table order; an explicit mark restricts the scan to that row.
|
||||
Accepted fills are motion-aligned across adjacent frames by default. The prior
|
||||
fill contributes only where its warped mask covers the current removal mask and
|
||||
@@ -181,10 +188,10 @@ inspection cannot independently verify the output. Microsoft's official
|
||||
is the external oracle: it reports pixel `Watermark` and embedded `C2PA` results
|
||||
separately; a control-positive, output-negative pair is the available per-file
|
||||
verification path. The API needs Azure credentials; the page a human can check
|
||||
without an account is <https://ai.azure.com/nextgen/validate>. Its verdict is
|
||||
weaker than the API's: it collapses watermark and C2PA into one rendered result
|
||||
and tops out at `Inconclusive` rather than a watermark-negative, so treat
|
||||
`Inconclusive` on a processed file as "not confirmed", not as "detected still".
|
||||
without an account is <https://ai.azure.com/nextgen/validate>. That page is the
|
||||
public provider oracle used for the measured removal certification. Its clean
|
||||
outcome is rendered as `Inconclusive`; the authenticated API exposes separate
|
||||
watermark and C2PA fields but is not a different class of certification.
|
||||
|
||||
Meta Muse Image stamps every output with Content Seal, a proprietary invisible
|
||||
pixel watermark, and ships no visible mark (the legacy `Imagined with AI`
|
||||
|
||||
@@ -25,8 +25,16 @@ icon-only variants need separate calibrated silhouettes.
|
||||
Some applications sign C2PA through an upstream model or infrastructure
|
||||
provider. For AI claims, exact product mappings in `claim_generator` therefore
|
||||
take precedence over issuer attribution. Supported mappings include Higgsfield
|
||||
AI, Topaz Labs Image API, and TikTok Ad Creative Toolbox; an unknown claim
|
||||
generator still falls back to the certificate issuer.
|
||||
AI, Recraft, Topaz Labs Image API, and TikTok Ad Creative Toolbox; an unknown
|
||||
claim generator still falls back to the certificate issuer.
|
||||
|
||||
**OpenRouter raster metadata survey (2026-09-02):** a paid Recraft V3 API
|
||||
output carried a valid C2PA claim with `claim_generator` `recraft.ai`, a
|
||||
`c2pa.created` action, and `trainedAlgorithmicMedia`; that exact generator now
|
||||
attributes the platform to Recraft. Paid Krea 2 Medium Turbo and Sourceful
|
||||
Riverflow V2 Fast API outputs carried no locally readable C2PA, XMP, EXIF, or
|
||||
container metadata. Their absence is evidence about those exact files and API
|
||||
routes, not a claim that every Krea or Riverflow export is metadata-free.
|
||||
|
||||
**ByteDance Volcano Engine (Volcengine)** — the cloud behind Doubao / Jimeng — signs its AI image output with a cert from `certificate_center@volcengine.com` + `trainedAlgorithmicMedia` (issuer `b"volcengine"` → "ByteDance (Volcano Engine)", platform "ByteDance Volcano Engine"); note this is the C2PA-signed surface, distinct from the XMP/PNG TC260 `AIGC` label Doubao also uses. ByteDance's **international brand (BytePlus / Seedream / Seededit)** signs the same content as **"Byteplus Pte. Ltd."**. The bare `volcengine` needle missed it, so BytePlus output was mis-attributed to "Adobe Firefly" through an incidental "Adobe XMP" toolkit string. Issuer `b"Byteplus"` maps directly to "BytePlus (ByteDance)". ByteDance's consumer app **Dreamina** (the international Jimeng brand) signs as **"Bytedance Pte. Ltd."** with a `Dreamina/x.y` claim generator but, unlike the Volcano Engine surface, ships **no `trainedAlgorithmicMedia`**. Issuer `b"Dreamina"` maps to "ByteDance Dreamina" with **`asserts_ai=True`**. Registering the broader **issuer** `b"Bytedance Pte"` was deliberately avoided because that same entity also signs non-AI CapCut edits; keying on the `Dreamina` generator token is precise.
|
||||
- **EXIF/XMP/PNG-text generator tag (caught by `exif_generator`):** **Ideogram** writes EXIF `Make="Ideogram AI"` (collected 2026-05-24 — no C2PA, no SynthID, no imwatermark; the Make tag is the only signal). Additional verified generator stamps include **NovelAI** (`Software`, `Source`, and `Title` PNG text chunks), **Reve** (`Software` or XMP `CreatorTool` = `reve.com`), and **Aphrodite AI** (`Make` or `Software` = `Aphrodite AI`).
|
||||
@@ -66,7 +74,7 @@ payloads. Removal remuxes either container through ffmpeg with stream copy.
|
||||
encoder and the carrier remains decodable.
|
||||
- **Invisible but NOT locally detectable (proprietary, API/oracle only — same wall as SynthID):** Amazon Titan Image Generator + Nova Canvas (Bedrock `DetectGeneratedContent` API), Kakao (new SynthID image adopter, May 2026), NVIDIA Cosmos (SynthID video). No local detector possible; treat like SynthID.
|
||||
- **C2PA 2.4 "Durable Content Credentials" (April 2026; verified against the spec) raise the bar for metadata stripping.** 2.4 defines soft bindings (an invisible watermark or a content fingerprint) plus a server-side manifest repository and a new `c2pa.repository-receipt` assertion. Per the spec: "if a C2PA manifest is removed from an asset, but a copy of that manifest remains in a provenance store elsewhere, the manifest and asset may be matched using available soft bindings." So our local `metadata --remove` deletes the *embedded* manifest, but a fingerprint/watermark soft binding can still re-link the image to its manifest in a repository server-side. Stripping the file is becoming necessary-but-not-sufficient against durable provenance. (Our parsers target the stable embedded-manifest format documented in C2PA 2.1 §11; that format is unchanged in 2.4 -- the new pieces are repository/soft-binding infra, not the on-file box layout, so no parser change is implied.) Spec: https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html We READ the soft-binding `alg`, preserve the structured assertion's signed `value`, and generate the display/type registry from the official C2PA JSON with `scripts/sync_c2pa_soft_bindings.py`. The packaged snapshot keeps runtime inspection offline and pins the exact upstream revision. Registration is name-only support: Adobe TrustMark remains the one locally decoded scheme (`trustmark_detector`) unless another compatible decoder is independently verified. Fingerprint entries remain re-linkability signals and are not mislabeled as pixel watermarks.
|
||||
- **Microsoft Paint and Photos InvisMark (reverse-engineered 2026-08-20):** Paint receives a per-generation GUID from remote prompt moderation, embeds it into locally generated pixels, and records the same value in `c2pa.soft-binding` under `com.microsoft.invismark.1`. The C2PA soft-binding registry independently identifies that algorithm as Microsoft Responsible AI InvisMark for image and video. Paint's 144-bit writer framing does not match the public repository's 100-bit pretrained checkpoint interface, so compatibility is not assumed. The parser reports the signed identifier; there is no validated local pixel decoder. Microsoft's external Content Provenance Detection API is the removal oracle because it reports `Watermark` separately from `C2PA`; a metadata-stripped, pixel-identical control must remain watermark-positive before an output-negative result is attributed to pixel removal. The no-account web page for the same check is <https://ai.azure.com/nextgen/validate> (its `Inconclusive` verdict is weaker than the API's separate watermark result). Sources: https://xusheng.dev/posts/reversing/mspaint_invisible_watermark/main/, https://github.com/c2pa-org/softbinding-algorithm-list/blob/main/softbinding-algorithm-list.json, and https://learn.microsoft.com/en-us/azure/ai-services/content-safety/how-to/how-to-provenance-detection
|
||||
- **Microsoft Paint and Photos InvisMark (reverse-engineered 2026-08-20):** Paint receives a per-generation GUID from remote prompt moderation, embeds it into locally generated pixels, and records the same value in `c2pa.soft-binding` under `com.microsoft.invismark.1`. The C2PA soft-binding registry independently identifies that algorithm as Microsoft Responsible AI InvisMark for image and video. Paint's 144-bit writer framing does not match the public repository's 100-bit pretrained checkpoint interface, so compatibility is not assumed. The parser reports the signed identifier; there is no validated local pixel decoder. Microsoft's external Content Provenance Detection API is the removal oracle because it reports `Watermark` separately from `C2PA`; a metadata-stripped, pixel-identical control must remain watermark-positive before an output-negative result is attributed to pixel removal. The no-account web page for the same check is <https://ai.azure.com/nextgen/validate>; its clean outcome is rendered as `Inconclusive`, and that public provider oracle is the surface used for the measured removal certification. Sources: https://xusheng.dev/posts/reversing/mspaint_invisible_watermark/main/, https://github.com/c2pa-org/softbinding-algorithm-list/blob/main/softbinding-algorithm-list.json, and https://learn.microsoft.com/en-us/azure/ai-services/content-safety/how-to/how-to-provenance-detection
|
||||
- **Built in the dated batch:** soft-binding vendor detection, IPTC Photo
|
||||
Metadata AI-disclosure fields, C2PA detection and stripping for supported
|
||||
ISOBMFF video, the optional Adobe TrustMark decoder, and temporally stabilized
|
||||
@@ -131,6 +139,58 @@ instead uses Florence-2 to identify arbitrary watermarks before LaMa
|
||||
inpainting. That is broader, but it carries a much heavier model and a less
|
||||
auditable detection boundary than the provider-specific synthetic path here.
|
||||
|
||||
**Aggregator video export survey (2026-09-03).** Four paid, neutral-prompt
|
||||
text-to-video jobs tested whether API access could reproduce the registered
|
||||
consumer-facing marks. None did. OpenRouter `bytedance/seedance-2.0-mini`
|
||||
(4 s, 480p, `watermark=true`, USD 0.0568316) returned a valid BytePlus C2PA
|
||||
manifest but no visible boxed-`AI` mark; SHA-256
|
||||
`19c1e323fbb085e5679374a8b646d65a5e902292ff65e33462828ba211d089f4`.
|
||||
OpenRouter `minimax/hailuo-3-max` (5 s, 480p,
|
||||
`aigc_watermark=true`, USD 0.25) returned a native TC260 AIGC label but no
|
||||
visible `MINIMAX | hailuo AI` composite; SHA-256
|
||||
`c850c79df6475e12a219ab6a4927b874c82a3ab783175f75acc6aa7513d2c303`.
|
||||
WaveSpeedAI `openai/sora-2/text-to-video` (4 s, 720p) and
|
||||
`kwaivgi/kling-v1.6-t2v-standard` (5 s, 720p) returned neither their registered
|
||||
visible marks nor locally readable provenance; SHA-256 respectively
|
||||
`85c29592fdfdac882a6536f6c27781c5d4f6a19b49681808eb744d0e33b63281`
|
||||
and `392c4bd279ac94fa573f051b514b243c933637fdc7d0dae2df4af1f2312a85d0`.
|
||||
Each result was checked through the explicit provider video path, not only the
|
||||
auto arbiter, and returned no stable mark. The files are not fixtures: the two
|
||||
clean exports assert no supported signal, while the OpenRouter outputs need
|
||||
their model-specific redistribution terms settled before public inclusion.
|
||||
For fixture collection, use the consumer surfaces that apply the marks rather
|
||||
than repeating these aggregator routes. In particular, the provider option
|
||||
names `watermark` and `aigc_watermark` proved to request machine-readable
|
||||
provenance on these routes, not the visible overlays their names might imply.
|
||||
|
||||
**Direct Google Flow control (2026-09-03).** Two authenticated Veo 3.1 Fast
|
||||
generations used the same neutral blue-mug scene at 720p for 20 Flow credits
|
||||
each. With the account's `Visible watermarking` setting off, the downloaded
|
||||
8-second MP4 had valid Google C2PA and SynthID but no visible mark (SHA-256
|
||||
`f15454c2adda75fd79fcb8561e24088fa715f560e3c300c9f68e22fbc7275a20`).
|
||||
That clean control exposed a false positive: the current auto arbiter selected
|
||||
`hailuo` on all 192 frames and consequently misattributed the platform to
|
||||
MiniMax, while the explicit `veo` path correctly found no mark. With the
|
||||
setting on, the second 8-second MP4 carried low-contrast `Veo` text at the fixed
|
||||
bottom-right position, and the shipped detector selected `veo` on all 192
|
||||
frames (SHA-256
|
||||
`e778194b545e34dafd2d5be58691031a070862890c41e6c527a652a114a7c7a4`).
|
||||
The marked file is committed as the real provider original; the clean control
|
||||
remains outside the repository until its Hailuo false positive is fixed and
|
||||
locked by a negative regression test. Google documents both the user-controlled
|
||||
visible-watermark setting and invisible SynthID on every Flow output.
|
||||
|
||||
**Direct Hailuo AI control (2026-09-03).** An authenticated MiniMax H3
|
||||
generation used a neutral blue-mug scene, 2K output, and 60 top-up credits. The
|
||||
download menu separately offered `Remove watermark` and `With Watermark`; the
|
||||
latter produced a 2944 x 1248, 5-second MP4 carrying the complete lower-right
|
||||
`MINIMAX | hailuo AI` composite and a TC260 AIGC label naming MiniMax as the
|
||||
producer. The shipped detector selected `hailuo` on all 124 frames (SHA-256
|
||||
`6152609e0339c443af79e244440e1b1050f3c615a50f76bfaf6146584e68142f`).
|
||||
This provider original is committed as the real Hailuo regression fixture and
|
||||
confirms that the direct consumer export differs from the metadata-only
|
||||
OpenRouter result above.
|
||||
|
||||
**Learned detectors change the visible-mark precision/recall tradeoff; they do not establish a universal separator.** The visible-watermark-detection literature has moved to learned segmentation and object detection (WDNet WACV'21 arXiv:2012.07616; SLBR ACM MM'21, open code and weights; the PRCV'18 large-scale detector; Su et al. survey 2025). The cited arXiv:1705.08593 paper reports a method that significantly reduces false matches and eliminates them after rejecting a small fraction of matches on its electron-microscopy task; it does not prove an information-theoretic limit for watermark detection. Learned watermark detectors also rely on large, pattern-diverse labeled datasets built with synthetic composites (PRCV'18: 60k images / 80 watermark classes; CLWD: 60k / 160 marks), and transfer depends on the diversity represented in training. Inference can be cheap (WDNet reports roughly 8 ms at 256x256), while the labeled-data and evaluation pipeline remain the larger project cost. A learned detector is therefore a possible future operating point, not evidence that the current NCC gate is theoretically optimal.
|
||||
|
||||
**Visible-mark landscape beyond the registry.** Since Muse Image (2026-07) Meta's own generation output carries no visible mark, only the invisible proprietary Content Seal; the legacy visible "Imagined with AI" mark belongs to the pre-2026 Meta AI / "Imagine" pipeline and remains unregistered (string verified, position not). For third-party images Meta relies on C2PA / IPTC, not a visible mark. The Samsung detector covers only the measured Italian text wordmark; no separate icon-only variant has been verified. Visible overlays and embedded metadata can usually be removed without changing the underlying generation model, which is the tool's premise.
|
||||
|
||||
@@ -38,11 +38,13 @@ MARKS = {
|
||||
# stacked and ITALIC-SLANTED. A rare one-line variant exists, but the stacked block
|
||||
# is dominant.
|
||||
"yuanbao_alpha.png": "元宝\nAI生成",
|
||||
# Kling (可灵) stamps a thin light-gray one-line "可灵AI 3.0" bottom-right (an
|
||||
# "Omni" suffix variant and a latin "KlingAI 3.0" variant also exist; the CJK
|
||||
# run without the suffix is the common core). The leading spiral logo is NOT
|
||||
# rendered (logos vary; the text run discriminates).
|
||||
# Older Kling (可灵) exports stamp a thin light-gray one-line "可灵AI 3.0"
|
||||
# bottom-right. The leading spiral logo is NOT rendered (logos vary; the text
|
||||
# run discriminates).
|
||||
"kling_alpha.png": "可灵AI 3.0",
|
||||
# Current IMAGE 3.0 exports use the Latin ``KlingAI 3.0`` run. Keep it as a
|
||||
# second installed silhouette rather than replacing the measured CJK variant.
|
||||
"kling_latin_alpha.png": "KlingAI 3.0",
|
||||
# The "cat-logo" candidate stamps an outline cat-head plus bold "AI生成",
|
||||
# bottom-right. It remains unregistered pending sufficient calibration coverage.
|
||||
"catlogo_alpha.png": "cat logo + AI生成",
|
||||
@@ -96,8 +98,13 @@ MARK_OPTS: dict[str, dict[str, Any]] = {
|
||||
"qingyan_alpha.png": {"font": "/System/Library/Fonts/Hiragino Sans GB.ttc", "font_index": 2},
|
||||
# LibLibAI uses an Arial-class grotesque.
|
||||
"liblib_alpha.png": {"font": "/System/Library/Fonts/Supplemental/Arial.ttf"},
|
||||
"kling_latin_alpha.png": {"font": "/System/Library/Fonts/HelveticaNeue.ttc", "font_index": 1},
|
||||
}
|
||||
|
||||
# ``kling_latin`` is a variant of the registered ``kling`` row, not a second
|
||||
# registry key, so it cannot be derived from ``mark_keys()`` above.
|
||||
_REGISTERED.add("kling_latin_alpha.png")
|
||||
|
||||
|
||||
def _fit_font(
|
||||
font_path: str,
|
||||
|
||||
@@ -123,6 +123,7 @@ C2PA_CLAIM_GENERATOR_PLATFORMS: tuple[tuple[str, str], ...] = (
|
||||
("firefly", "Adobe Firefly"),
|
||||
("dreamina", "ByteDance Dreamina"),
|
||||
("higgsfield ai", "Higgsfield AI"),
|
||||
("recraft.ai", "Recraft"),
|
||||
("topaz labs image api", "Topaz Labs"),
|
||||
("tiktok ad creative toolbox", "TikTok Ad Creative Toolbox"),
|
||||
)
|
||||
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -1,19 +1,21 @@
|
||||
"""Kling AI (可灵AI, Kuaishou) visible watermark detector/localizer.
|
||||
|
||||
Kling AI stamps its generations with a thin, light-gray "可灵AI 3.0" text strip in the
|
||||
bottom-right corner, preceded by the vendor's spiral logo (not part of the detection
|
||||
silhouette -- logos vary between releases, the text run is what discriminates).
|
||||
Known variants: an "Omni" suffix release, a latin "KlingAI 3.0" release, and a
|
||||
version-less "可灵AI" -- the silhouette targets the common "可灵AI 3.0" core, so the
|
||||
suffix variants are only caught when the core run is bold enough (measured below).
|
||||
Kling AI stamps its generations with a thin, light-gray text strip in the
|
||||
bottom-right corner, preceded by the vendor's spiral logo (not part of the
|
||||
detection silhouette -- logos vary between releases, the text run is what
|
||||
discriminates). Separate silhouettes cover the older "可灵AI 3.0" release and
|
||||
the current IMAGE 3.0 "KlingAI 3.0" release. An "Omni" suffix and a version-less
|
||||
"可灵AI" remain outside the calibrated pair.
|
||||
|
||||
Detection matches the bundled glyph silhouette against the corner. Removal unions
|
||||
the pixel-derived footprint with that silhouette aligned to the winning match box,
|
||||
the pixel-derived footprint with the known silhouettes aligned to the winning match box,
|
||||
then sends the hybrid mask through the shared **localize -> fill** path in
|
||||
``region_eraser``; it is not reverse-alpha. The asset
|
||||
(``assets/kling_alpha.png``) is a font-rendered synthetic silhouette from
|
||||
``scripts/render_vendor_silhouettes.py``, never cut from an upload. The detector also
|
||||
feeds ``identify`` as the medium-confidence ``visible_kling`` signal via the registry.
|
||||
``region_eraser``; it is not reverse-alpha. This module supplies two tuned
|
||||
:class:`TextMarkConfig` instances (``assets/kling_alpha.png`` and
|
||||
``assets/kling_latin_alpha.png`` -- font-rendered synthetic silhouettes from
|
||||
``scripts/render_vendor_silhouettes.py``, never cut from an upload). The detector
|
||||
also feeds ``identify`` as the medium-confidence ``visible_kling`` signal via the
|
||||
registry.
|
||||
|
||||
EVERY tuned number below was measured on the vendor cohort (30 TC260 carriers whose
|
||||
producer USCC 91110108335469089C names the entity, 2026-07-21; harness
|
||||
@@ -25,13 +27,14 @@ producer USCC 91110108335469089C names the entity, 2026-07-21; harness
|
||||
box fractions below are fitted from the measured absolute mark rects.
|
||||
* ``alpha_height_frac`` comes from the silhouette aspect (0.239) at the fitted
|
||||
width, matching the aspect the fit converged on (0.25).
|
||||
* Gate 0.35, one step above the clean arm's max: on the cohort-vs-clean run
|
||||
* The CJK gate is 0.35, one step above the clean arm's max: on the cohort-vs-clean run
|
||||
(cohort-contamination-guarded, 286 hand-labeled clean frames) the clean arm
|
||||
scored p99 0.304 / max 0.320, and every cohort frame >= 0.35 carries a visible
|
||||
可灵AI 3.0 mark (9 of ~19 eyeballed visible marks fire = ~47% recall of visible
|
||||
marks; the misses are the faint "Omni"-suffix release, the latin "KlingAI"
|
||||
release and the version-less "可灵AI", which score 0.17-0.25 and cannot be
|
||||
reached without engulfing the clean arm).
|
||||
marks; the misses are the faint "Omni"-suffix release and the version-less
|
||||
"可灵AI", which score 0.17-0.25 and cannot be reached without engulfing the
|
||||
clean arm). The separately measured Latin IMAGE 3.0 variant is documented
|
||||
beside ``_LATIN_CONFIG`` below.
|
||||
* STRICT ONLY (``provenance_ncc_factor`` 1.0): the sub-gate band holds real Kling
|
||||
variants AND the clean arm's top (clean p90 0.220 vs variant marks at 0.17-0.25
|
||||
-- they overlap), so a provenance-relaxed arm cannot separate them. No
|
||||
@@ -49,6 +52,7 @@ producer USCC 91110108335469089C names the entity, 2026-07-21; harness
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import cv2
|
||||
@@ -121,6 +125,23 @@ _CONFIG = TextMarkConfig(
|
||||
provenance_ncc_factor=1.0,
|
||||
)
|
||||
|
||||
# Direct Kling IMAGE 3.0 export, 2026-09-04: the current Latin run measures
|
||||
# 0.095 x 0.028 of the short side inside the same bottom-right locate box. The
|
||||
# narrow ladder covers small rasterization shifts without admitting any of the
|
||||
# 94 available neighboring real/synthetic image controls (max 0.349, versus
|
||||
# 0.429 on the provider original). A deliberately adversarial solid corner blob
|
||||
# reaches 0.379, so the 0.40 gate stays above both measured negative arms. Keep
|
||||
# this a separate silhouette and gate:
|
||||
# replacing the CJK template would discard the older measured release.
|
||||
_LATIN_CONFIG = replace(
|
||||
_CONFIG,
|
||||
asset_name="kling_latin_alpha.png",
|
||||
alpha_width_frac=0.095,
|
||||
alpha_height_frac=0.028,
|
||||
ladder=(0.9, 1.0, 1.1),
|
||||
detect_ncc_threshold=0.40,
|
||||
)
|
||||
|
||||
|
||||
def _alpha_template() -> NDArray[Any] | None:
|
||||
"""The bundled Kling AI alpha template (float [0,1]), or None."""
|
||||
@@ -133,10 +154,29 @@ def _glyph_silhouette() -> NDArray[Any] | None:
|
||||
|
||||
|
||||
class KlingEngine(TextMarkEngine):
|
||||
"""Detect/localize the visible Kling AI "可灵AI 3.0" watermark (locate -> mask; mask feeds the fill)."""
|
||||
"""Detect/localize Kling AI's CJK and Latin 3.0 marks (locate -> mask -> fill)."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__(_CONFIG)
|
||||
self._latin = TextMarkEngine(_LATIN_CONFIG)
|
||||
|
||||
@staticmethod
|
||||
def _best(*detections: TextMarkDetection) -> TextMarkDetection:
|
||||
"""Prefer an accepted variant, then retain the strongest rejected score."""
|
||||
return max(detections, key=lambda detection: (detection.detected, detection.confidence))
|
||||
|
||||
def detect(self, image: NDArray[Any], *, provenance: bool = False) -> TextMarkDetection:
|
||||
"""Return the strongest CJK or Latin Kling wordmark verdict."""
|
||||
return self._best(
|
||||
super().detect(image, provenance=provenance),
|
||||
self._latin.detect(image, provenance=provenance),
|
||||
)
|
||||
|
||||
def detect_both(self, image: NDArray[Any] | None) -> tuple[TextMarkDetection, TextMarkDetection]:
|
||||
"""Scan each immutable variant once and combine strict/relaxed verdicts."""
|
||||
cjk_strict, cjk_relaxed = super().detect_both(image)
|
||||
latin_strict, latin_relaxed = self._latin.detect_both(image)
|
||||
return self._best(cjk_strict, latin_strict), self._best(cjk_relaxed, latin_relaxed)
|
||||
|
||||
def footprint_mask(
|
||||
self,
|
||||
@@ -146,7 +186,7 @@ class KlingEngine(TextMarkEngine):
|
||||
dilate: int | None = None,
|
||||
detection: TextMarkDetection | None = None,
|
||||
) -> NDArray[Any] | None:
|
||||
"""Add the detector-aligned Kling core to the pixel-derived footprint.
|
||||
"""Add detector-aligned Kling cores to the pixel-derived footprint.
|
||||
|
||||
The legacy mask remains in the union because it can cover variant-specific
|
||||
strokes outside the synthetic core. The aligned alpha closes holes caused by
|
||||
@@ -159,17 +199,19 @@ class KlingEngine(TextMarkEngine):
|
||||
|
||||
det = detection if detection is not None else self.detect(image)
|
||||
legacy = super().footprint_mask(image, force=False, dilate=dilate, detection=det)
|
||||
alpha = _alpha_template()
|
||||
if alpha is None:
|
||||
return legacy
|
||||
radius = _FOOTPRINT_DILATE if dilate is None else max(0, dilate)
|
||||
core = self._aligned_alpha_mask(
|
||||
image,
|
||||
det,
|
||||
alpha,
|
||||
alpha_floor=_FOOTPRINT_ALPHA_FLOOR,
|
||||
dilate=radius,
|
||||
)
|
||||
if core is None:
|
||||
return legacy
|
||||
return core if legacy is None else cv2.bitwise_or(legacy, core)
|
||||
result = legacy
|
||||
for config in (_CONFIG, _LATIN_CONFIG):
|
||||
alpha = _text_mark_engine.load_alpha_template(config.asset_name)
|
||||
if alpha is None:
|
||||
continue
|
||||
core = self._aligned_alpha_mask(
|
||||
image,
|
||||
det,
|
||||
alpha,
|
||||
alpha_floor=_FOOTPRINT_ALPHA_FLOOR,
|
||||
dilate=radius,
|
||||
)
|
||||
if core is not None:
|
||||
result = core if result is None else cv2.bitwise_or(result, core)
|
||||
return result
|
||||
@@ -820,6 +820,7 @@ def synthid_source(image_path: Path, *, c2pa_info: dict[str, Any] | None = None)
|
||||
from remove_ai_watermarks._internal.c2pa import (
|
||||
c2pa_info_has_invalid_credential,
|
||||
extract_c2pa_info,
|
||||
soft_binding_registry_entries_in,
|
||||
synthid_evidence_vendors_in,
|
||||
)
|
||||
|
||||
@@ -832,6 +833,11 @@ def synthid_source(image_path: Path, *, c2pa_info: dict[str, Any] | None = None)
|
||||
vendors = c2pa.get("synthid_vendors")
|
||||
if vendors:
|
||||
return ", ".join(vendors)
|
||||
soft_binding_algorithm = c2pa.get("soft_binding_algorithm")
|
||||
if soft_binding_algorithm:
|
||||
entries = soft_binding_registry_entries_in(str(soft_binding_algorithm).encode())
|
||||
if any(entry.kind == "watermark" for entry in entries) or not entries:
|
||||
return None
|
||||
|
||||
# Non-PNG containers (JPEG APP11, WebP, AVIF/HEIF/JXL uuid box) keep the
|
||||
# C2PA manifest where the PNG parser can't reach it. Binary-scan for the
|
||||
@@ -842,8 +848,6 @@ def synthid_source(image_path: Path, *, c2pa_info: dict[str, Any] | None = None)
|
||||
ai_source = b"trainedAlgorithmicMedia" in data or b"TrainedAlgorithmicMedia" in data
|
||||
if not (has_c2pa and ai_source):
|
||||
return None
|
||||
from remove_ai_watermarks._internal.c2pa import soft_binding_registry_entries_in
|
||||
|
||||
# A declared watermark blocks a second, generic watermark attribution. A
|
||||
# content fingerprint does not suppress independent SynthID evidence.
|
||||
if any(entry.kind == "watermark" for entry in soft_binding_registry_entries_in(data)):
|
||||
|
||||
@@ -271,31 +271,32 @@ def _hailuo_template() -> NDArray[Any]:
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _kling_templates() -> tuple[NDArray[Any], ...]:
|
||||
"""Return synthetic font variants for the Kling wordmark core."""
|
||||
canvas = Image.new("L", (430, 104), 0)
|
||||
draw = ImageDraw.Draw(canvas)
|
||||
draw.text(
|
||||
(2, 12),
|
||||
"KLING AI",
|
||||
font=_scalable_default_font(64),
|
||||
fill=255,
|
||||
stroke_width=1,
|
||||
stroke_fill=255,
|
||||
)
|
||||
templates = [_crop_nonzero(np.asarray(canvas, dtype=np.uint8))]
|
||||
for font in (cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_DUPLEX):
|
||||
cv_template = np.zeros((100, 500), dtype=np.uint8)
|
||||
cv2.putText(
|
||||
cv_template,
|
||||
"KLING AI",
|
||||
(2, 72),
|
||||
font,
|
||||
2.2,
|
||||
255,
|
||||
3,
|
||||
cv2.LINE_AA,
|
||||
"""Return synthetic font and capitalization variants for the Kling wordmark core."""
|
||||
templates: list[NDArray[Any]] = []
|
||||
for text in ("KLING AI", "KlingAI"):
|
||||
canvas = Image.new("L", (430, 104), 0)
|
||||
ImageDraw.Draw(canvas).text(
|
||||
(2, 12),
|
||||
text,
|
||||
font=_scalable_default_font(64),
|
||||
fill=255,
|
||||
stroke_width=1,
|
||||
stroke_fill=255,
|
||||
)
|
||||
templates.append(_crop_nonzero(cv_template))
|
||||
templates.append(_crop_nonzero(np.asarray(canvas, dtype=np.uint8)))
|
||||
for font in (cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_DUPLEX):
|
||||
cv_template = np.zeros((100, 500), dtype=np.uint8)
|
||||
cv2.putText(
|
||||
cv_template,
|
||||
text,
|
||||
(2, 72),
|
||||
font,
|
||||
2.2,
|
||||
255,
|
||||
3,
|
||||
cv2.LINE_AA,
|
||||
)
|
||||
templates.append(_crop_nonzero(cv_template))
|
||||
return tuple(templates)
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Entries:
|
||||
- ``doubao`` -- ByteDance Doubao "豆包AI生成" text strip, bottom-right.
|
||||
- ``jimeng`` -- ByteDance Jimeng / Dreamina "★ 即梦AI" wordmark, bottom-right.
|
||||
- ``qwen`` -- Alibaba Cloud Qwen "千问AI生成" text strip, bottom-right.
|
||||
- ``kling`` -- Kuaishou Kling AI "可灵AI 3.0" text strip, bottom-right.
|
||||
- ``kling`` -- Kuaishou Kling AI "可灵AI 3.0" / "KlingAI 3.0" strip, bottom-right.
|
||||
- ``yuanbao`` -- Tencent Yuanbao "元宝 / AI生成" two-line mark, bottom-right.
|
||||
- ``samsung`` -- Samsung Galaxy AI "Contenuti generati dall'AI" strip, bottom-left.
|
||||
- ``jimeng_pill`` -- Jimeng-basic "AI生成" pill, top-left (capture-less).
|
||||
@@ -726,9 +726,9 @@ _REGISTRY: tuple[KnownMark, ...] = (
|
||||
),
|
||||
_text_mark(
|
||||
"kling",
|
||||
"Kling AI 可灵AI 3.0 text",
|
||||
"Kling AI 可灵AI / KlingAI 3.0 text",
|
||||
"bottom-right",
|
||||
platform="Kuaishou Kling AI (visible 可灵AI 3.0 mark detected)",
|
||||
platform="Kuaishou Kling AI (visible 可灵AI / KlingAI 3.0 mark detected)",
|
||||
tc260_producer_codes=("91110108335469089C",),
|
||||
),
|
||||
_text_mark(
|
||||
|
||||
@@ -7,6 +7,7 @@ against the real committed C2PA / IPTC fixtures in data/fixtures/provenance/.
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -463,6 +464,7 @@ class TestIdentifyNonPng:
|
||||
("claim_generator", "platform"),
|
||||
[
|
||||
("Higgsfield AI", "Higgsfield AI"),
|
||||
("recraft.ai", "Recraft"),
|
||||
("Topaz Labs Image API", "Topaz Labs"),
|
||||
("TIKTOK AD Creative Toolbox", "TikTok Ad Creative Toolbox"),
|
||||
],
|
||||
@@ -491,6 +493,78 @@ class TestIdentifyNonPng:
|
||||
assert report.platform == platform
|
||||
assert claim_generator in next(s.detail for s in report.signals if s.name == "c2pa")
|
||||
|
||||
def test_real_recraft_c2pa_fixture(self):
|
||||
report = identify(SAMPLES_DIR / "recraft-v3.webp", check_visible=False)
|
||||
|
||||
assert report.is_ai_generated is True
|
||||
assert report.confidence == "high"
|
||||
assert report.platform == "Recraft"
|
||||
assert any(signal.name == "c2pa" and "recraft.ai" in signal.detail for signal in report.signals)
|
||||
|
||||
def test_real_krea_api_fixture_has_no_local_provenance(self):
|
||||
report = identify(SAMPLES_DIR / "krea-2-medium-turbo.png", check_visible=False)
|
||||
|
||||
assert report.is_ai_generated is None
|
||||
assert report.platform is None
|
||||
assert report.signals == []
|
||||
|
||||
def test_real_direct_kling_fixture_has_tc260_and_current_visible_mark(self):
|
||||
path = SAMPLES_DIR.parent / "visible" / "kling" / "provider-original-direct.png"
|
||||
report = identify(path, check_visible=True)
|
||||
|
||||
assert report.is_ai_generated is True
|
||||
assert any(
|
||||
signal.name == "aigc" and "001191110108335469089C10100" in signal.detail for signal in report.signals
|
||||
)
|
||||
assert any(signal.name == "visible_kling" for signal in report.signals)
|
||||
|
||||
@pytest.mark.parametrize("filename", ["qwen-image.png", "seedream-v4.jpg"])
|
||||
def test_real_wavespeed_api_fixture_has_no_local_provenance(self, filename):
|
||||
report = identify(SAMPLES_DIR / filename, check_visible=False)
|
||||
|
||||
assert report.is_ai_generated is None
|
||||
assert report.platform is None
|
||||
assert report.signals == []
|
||||
|
||||
def test_real_wavespeed_hunyuan_fixture_has_fal_c2pa(self):
|
||||
path = SAMPLES_DIR / "hunyuan-image-3.png"
|
||||
assert hashlib.sha256(path.read_bytes()).hexdigest() == (
|
||||
"6ae2ac073ac79b02b0934c905364f200420c2ff60fea232bd9e0a5fca785cc09"
|
||||
)
|
||||
|
||||
report = identify(path, check_visible=False, check_invisible=False)
|
||||
|
||||
assert report.is_ai_generated is True
|
||||
assert report.platform == "fal.ai"
|
||||
assert report.confidence == "high"
|
||||
assert any(signal.name == "c2pa" and "fal-ai/hunyuan-image" in signal.detail for signal in report.signals)
|
||||
|
||||
def test_real_wavespeed_kling_fixture_has_tc260_metadata(self):
|
||||
path = SAMPLES_DIR / "kling-image-v3.png"
|
||||
assert hashlib.sha256(path.read_bytes()).hexdigest() == (
|
||||
"501ab865b47ba59b64bc0f68118300744b0d5c7be2fa4e2ecbb3a78de5d8a82b"
|
||||
)
|
||||
|
||||
report = identify(path, check_visible=False, check_invisible=False)
|
||||
|
||||
assert report.is_ai_generated is True
|
||||
assert report.confidence == "high"
|
||||
aigc = next(signal for signal in report.signals if signal.name == "aigc")
|
||||
assert "001191110108335469089C10100" in aigc.detail
|
||||
|
||||
def test_real_qwen_create_fixture_has_tc260_metadata(self):
|
||||
path = SAMPLES_DIR / "qwen-create-qwen-image-2.png"
|
||||
assert hashlib.sha256(path.read_bytes()).hexdigest() == (
|
||||
"60c39ed8aedb081193c62289be549785e74d31fc8d071961003fabd74712429d"
|
||||
)
|
||||
|
||||
report = identify(path, check_visible=False, check_invisible=False)
|
||||
|
||||
assert report.is_ai_generated is True
|
||||
assert report.confidence == "high"
|
||||
aigc = next(signal for signal in report.signals if signal.name == "aigc")
|
||||
assert "001191440101MA9Y9T4H7A00000" in aigc.detail
|
||||
|
||||
def test_dreamina_attributed_without_source_type(self, tmp_path: Path):
|
||||
# Dreamina (ByteDance's international Jimeng brand) signs C2PA as
|
||||
# "Bytedance Pte. Ltd." with a "Dreamina/x.y" claim generator and NO
|
||||
@@ -1333,6 +1407,43 @@ class TestIdentifySoftBinding:
|
||||
assert watermark_id in invismark.detail
|
||||
assert any("may remain in the pixels" in caveat for caveat in report.caveats)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("filename", "watermark_id", "sha256"),
|
||||
[
|
||||
(
|
||||
"microsoft-invismark.png",
|
||||
"19b070a1-23f0-40eb-826c-cade306337eb",
|
||||
"be27ac7c351e7f381dc69e140ca3611ecd9db81e40926c68050ceffdd0ce6c04",
|
||||
),
|
||||
(
|
||||
"microsoft-paint-invismark.png",
|
||||
"a4ed421e-7c37-4409-998e-f8788c564572",
|
||||
"74eda22d210d534fcb5b75bedf8acd3bd110b48a95f4b9e546cd34f546effc05",
|
||||
),
|
||||
(
|
||||
"microsoft-bing-image-creator.jpg",
|
||||
"aec9a34e-665f-4549-9c02-9d29337a5de6",
|
||||
"55cad5355b6eeeb25f84ea074f85c0ea55b82d63c27f43e3429bb75f28734ac7",
|
||||
),
|
||||
(
|
||||
"../visible/microsoft/provider-original.png",
|
||||
"975290d4-9c2f-4359-ad5a-92c5b5b850a4",
|
||||
"0e76fb8aa0540b18fee4d63ac4b5fd63c7eee310474e896d21d27e668403afe7",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_real_microsoft_invismark_fixture(self, filename, watermark_id, sha256):
|
||||
path = SAMPLES_DIR / filename
|
||||
assert hashlib.sha256(path.read_bytes()).hexdigest() == sha256
|
||||
|
||||
report = identify(path, check_visible=False)
|
||||
|
||||
assert report.platform == "Microsoft (Copilot / Designer)"
|
||||
soft_binding = next(signal for signal in report.signals if signal.name == "soft_binding")
|
||||
assert "com.microsoft.invismark.1" in soft_binding.detail
|
||||
assert watermark_id in soft_binding.detail
|
||||
assert any(signal.name == "invismark" for signal in report.signals)
|
||||
|
||||
|
||||
class TestIdentifyIptcAi:
|
||||
"""IPTC 2025.1 AISystemUsed drives an AI verdict + platform attribution."""
|
||||
|
||||
@@ -6,15 +6,12 @@ both identify them and match the upstream decoder bit for bit.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from pathlib import Path
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from remove_ai_watermarks.invisible_watermark import (
|
||||
_BITS_48,
|
||||
_SD1_STRING,
|
||||
@@ -101,6 +98,10 @@ class TestRaveledHaarPass:
|
||||
|
||||
|
||||
class TestDetect:
|
||||
def test_committed_sdxl_carrier(self):
|
||||
path = Path(__file__).parents[1] / "data/fixtures/provenance/sdxl-dwt-dct.png"
|
||||
assert detect_invisible_watermark(path) == "Stable Diffusion XL"
|
||||
|
||||
def test_in_tree_decoder_matches_upstream(self, tmp_path: Path):
|
||||
from imwatermark import WatermarkDecoder
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Tests for the Kling (可灵AI 3.0) visible-watermark engine (localize -> fill).
|
||||
"""Tests for the Kling CJK/Latin 3.0 visible-watermark engine (localize -> fill).
|
||||
|
||||
Every tuned constant in ``kling_engine`` was measured on the 30-frame vendor
|
||||
cohort (2026-07-21, ``scripts/vendor_mark_calibrate.py``); these tests pin the
|
||||
@@ -18,6 +18,7 @@ from remove_ai_watermarks import watermark_registry as registry
|
||||
from remove_ai_watermarks.kling_engine import (
|
||||
_ALPHA_HEIGHT_FRAC,
|
||||
_ALPHA_WIDTH_FRAC,
|
||||
_LATIN_CONFIG,
|
||||
KlingEngine,
|
||||
_alpha_template,
|
||||
_glyph_silhouette,
|
||||
@@ -78,6 +79,11 @@ class TestConfig:
|
||||
# gate must sit above that with margin.
|
||||
assert KlingEngine().config.detect_ncc_threshold > 0.32
|
||||
|
||||
def test_latin_variant_keeps_its_measured_narrow_ladder(self):
|
||||
assert _LATIN_CONFIG.asset_name == "kling_latin_alpha.png"
|
||||
assert _LATIN_CONFIG.ladder == (0.9, 1.0, 1.1)
|
||||
assert _LATIN_CONFIG.detect_ncc_threshold == 0.40
|
||||
|
||||
def test_registry_row(self):
|
||||
mark = registry.get_mark("kling")
|
||||
assert mark.location == "bottom-right"
|
||||
@@ -126,6 +132,12 @@ class TestDetect:
|
||||
assert eng.detect(wm).detected
|
||||
assert not eng.detect(cv2.resize(wm, (150, 112))).detected
|
||||
|
||||
def test_metadata_only_kling_api_export_is_not_a_visible_mark(self):
|
||||
path = Path(__file__).resolve().parents[1] / "data" / "fixtures" / "provenance" / "kling-image-v3.png"
|
||||
image = cv2.imread(str(path))
|
||||
assert image is not None
|
||||
assert not KlingEngine().detect(image).detected
|
||||
|
||||
|
||||
class TestFootprintMaskAndRemoval:
|
||||
def test_removes_composed_mark(self):
|
||||
|
||||
@@ -560,6 +560,11 @@ class TestSynthIDSource:
|
||||
assert synthid_source(SAMPLES_DIR / "firefly-1.png") is None
|
||||
assert "synthid_watermark" not in get_ai_metadata(SAMPLES_DIR / "firefly-1.png")
|
||||
|
||||
def test_microsoft_invismark_is_not_openai_synthid(self):
|
||||
path = SAMPLES_DIR / "microsoft-paint-invismark.png"
|
||||
assert synthid_source(path) is None
|
||||
assert "synthid_watermark" not in get_ai_metadata(path)
|
||||
|
||||
def test_non_ai_image_is_not_synthid_source(self, clean_photo: Path):
|
||||
assert synthid_source(clean_photo) is None
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
"""Jimeng-basic 'AI生成' pill: capture-less mark (detect via synthetic silhouette
|
||||
edge-NCC, remove via inpaint). No model download -- cv2 fallback / pure logic only."""
|
||||
"""Jimeng-basic 'AI生成' pill: synthetic-silhouette edge-NCC and inpainting.
|
||||
|
||||
No model download -- cv2 fallback / pure logic only. The separate visible-example
|
||||
suite exercises the detector against a published real-world carrier.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ Two failures this suite exists to catch:
|
||||
generated from the engines' measured geometry, so this is a regression tripwire).
|
||||
|
||||
The examples are SYNTHETIC (``scripts/render_visible_examples.py`` composites the
|
||||
committed silhouettes onto a generated base).
|
||||
committed silhouettes onto a generated base). Documented provider originals and
|
||||
provider frames are separate regression inputs and remain byte-for-byte copies of
|
||||
their sources.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -18,11 +20,26 @@ import pytest
|
||||
from remove_ai_watermarks import watermark_registry as wr
|
||||
from remove_ai_watermarks.image_io import imread
|
||||
from remove_ai_watermarks.video import VIDEO_VISIBLE_MARKS, identify_video
|
||||
from remove_ai_watermarks.video_visible import detect_sora_frame
|
||||
|
||||
_ROOT = Path(__file__).resolve().parents[1]
|
||||
_GALLERY = _ROOT / "data" / "fixtures" / "visible"
|
||||
|
||||
_IMAGE_KEYS = [m.key for m in wr.known_marks()]
|
||||
_PROVIDER_ORIGINALS = {
|
||||
"baidu": "provider-original.jpeg",
|
||||
"jimeng_pill": "provider-published-example.jpg",
|
||||
"kling": "provider-original-direct.png",
|
||||
"microsoft": "provider-original.png",
|
||||
"qwen": "provider-original.png",
|
||||
"yuanbao": "provider-original.png",
|
||||
}
|
||||
_VIDEO_PROVIDER_ORIGINALS = {
|
||||
"hailuo": "provider-original.mp4",
|
||||
"kling": "provider-original.mp4",
|
||||
"sora": "provider-original.mp4",
|
||||
"veo": "provider-original.mp4",
|
||||
}
|
||||
|
||||
|
||||
class TestGallery:
|
||||
@@ -42,6 +59,13 @@ class TestGallery:
|
||||
extra = sorted(p.name for p in _GALLERY.iterdir() if p.name not in known)
|
||||
assert extra == [], f"gallery holds unregistered examples: {extra}; remove or register them"
|
||||
|
||||
@pytest.mark.parametrize("key", sorted(_PROVIDER_ORIGINALS))
|
||||
def test_engine_detects_provider_original(self, key: str) -> None:
|
||||
img = imread(str(_GALLERY / key / _PROVIDER_ORIGINALS[key]))
|
||||
assert img is not None, key
|
||||
det = wr.get_mark(key).detect(img, provenance=False)
|
||||
assert det.detected, f"{key}: confidence {det.confidence:.3f} on provider original"
|
||||
|
||||
|
||||
class TestVideoGallery:
|
||||
def test_every_registered_video_mark_has_an_example(self) -> None:
|
||||
@@ -55,3 +79,14 @@ class TestVideoGallery:
|
||||
for key in VIDEO_VISIBLE_MARKS:
|
||||
rep = identify_video(_GALLERY / key / "example.mp4", check_visible=True)
|
||||
assert rep.visible_mark == key, f"{key}: selection returned {rep.visible_mark!r}"
|
||||
|
||||
@pytest.mark.parametrize("key", sorted(_VIDEO_PROVIDER_ORIGINALS))
|
||||
def test_selection_accepts_provider_original(self, key: str) -> None:
|
||||
rep = identify_video(_GALLERY / key / _VIDEO_PROVIDER_ORIGINALS[key], check_visible=True)
|
||||
assert rep.visible_mark == key, f"{key}: selection returned {rep.visible_mark!r}"
|
||||
|
||||
def test_sora_frame_localizer_accepts_provider_frame(self) -> None:
|
||||
img = imread(str(_GALLERY / "sora" / "provider-frame.jpg"))
|
||||
assert img is not None
|
||||
det = detect_sora_frame(img)
|
||||
assert det.confidence >= 0.60, f"sora: confidence {det.confidence:.3f} on provider frame"
|
||||