Skip to main content

Invisible & visible watermarking SDK for AI-generated images and video

Project description

clawID

Invisible & visible watermarking SDK for AI-generated images and video.

PyPI Python CI License: MIT

A research project by hawky.ai — the AI content provenance platform.

clawID embeds a UUID-based watermark into images and video frames — invisible to the human eye but detectable by the SDK. Inspired by Google SynthID. Built for AI-generated asset provenance tracking.

Links: PyPI · GitHub · Hugging Face Space · hawky.ai


Features

  • Invisible watermarking via DWT-QIM (Discrete Wavelet Transform + Quantization Index Modulation)
  • Resize-robust mode (algorithm='fm') — survives ±35% resize, JPEG compression, and minor edits
  • Visible watermarking — overlay text/logo with configurable opacity and position
  • Video support — watermark every Nth frame; detect from any single watermarked frame
  • REST API — FastAPI server with /embed and /detect endpoints
  • Storage backends — SQLite, PostgreSQL, MongoDB, Redis
  • CLIclawid embed, clawid detect, clawid embed-video, clawid detect-video

Installation

# Core (images only)
pip install clawid

# With video support
pip install "clawid[video]"

# With REST API
pip install "clawid[api]"

# Everything
pip install "clawid[all]"

Quick Start

Images

from clawid import embed, detect

# Embed invisible watermark
meta = embed(
    source='photo.jpg',
    output_path='photo_wm.png',
    metadata={'uid': 'creator123', 'platform': 'hawky.ai'},
)
print(meta['clawid'])  # e.g. "3f2a1b4c-..."

# Detect
result = detect('photo_wm.png')
print(result['uid'])       # creator123
print(result['platform'])  # hawky.ai

Resize-robust mode

meta = embed(
    source='photo.jpg',
    output_path='photo_wm.png',
    metadata={'uid': 'creator123'},
    algorithm='fm',   # survives ±35% resize
)

Video

from clawid import embed_video, detect_video

meta = embed_video(
    'input.mp4',
    'output_wm.mp4',
    metadata={'uid': 'creator123', 'platform': 'hawky.ai'},
    frame_stride=5,   # watermark every 5th frame
)

result = detect_video('output_wm.mp4')
print(result['uid'])  # creator123

Visible watermark

meta = embed(
    source='photo.jpg',
    output_path='photo_wm.png',
    metadata={'uid': 'creator123'},
    mode='visible',     # or 'both' for invisible + visible
    opacity=0.6,
    position='bottom-right',
)

CLI

# Embed
clawid embed -i photo.jpg -o photo_wm.png --uid creator123 --platform hawky.ai

# Embed (resize-robust)
clawid embed -i photo.jpg -o photo_wm.png --uid creator123 --algorithm fm

# Detect
clawid detect -i photo_wm.png

# Video
clawid embed-video -i input.mp4 -o output_wm.mp4 --uid creator123
clawid detect-video -i output_wm.mp4

# Save to SQLite store on embed, enrich on detect
clawid embed -i photo.jpg -o wm.png --uid creator123 --store sqlite:///clawid.db
clawid detect -i wm.png --store sqlite:///clawid.db

REST API

pip install "clawid[api]"
clawid serve --store sqlite:///clawid.db --port 8000

Endpoints:

Method Path Description
POST /embed Upload image, get back watermarked image + metadata
POST /detect Upload image, get back detected metadata
GET /docs Interactive Swagger UI
# Embed via API
curl -X POST http://localhost:8000/embed \
  -F "file=@photo.jpg" \
  -F "uid=creator123" \
  -F "platform=hawky.ai" \
  --output photo_wm.png

# Detect via API
curl -X POST http://localhost:8000/detect \
  -F "file=@photo_wm.png"

Storage Backends

from clawid.storage import from_uri

# SQLite (local)
with from_uri('sqlite:///clawid.db') as store:
    store.save(meta['clawid'], meta)
    record = store.get(meta['clawid'])

# PostgreSQL
with from_uri('postgresql://user:pass@localhost/mydb') as store:
    store.save(meta['clawid'], meta)

# MongoDB
with from_uri('mongodb://localhost:27017/mydb') as store:
    store.save(meta['clawid'], meta)

# Redis
with from_uri('redis://localhost:6379/0') as store:
    store.save(meta['clawid'], meta)

How It Works

Invisible watermark (DWT-QIM)

The payload (UUID + metadata, CBOR-encoded + CRC-checked) is serialised to bits, then each bit is embedded by quantizing a coefficient in the Haar wavelet LL2 sub-band. Each LL2 coefficient represents a 4×4 pixel block, so a change of delta/16 ≈ 2+ pixels per block — above the uint8 quantization step — making the watermark survive JPEG compression and format round-trips.

Mode Delta PSNR Survives
qim (default) 32 ~51 dB PNG/JPEG q≥75, minor edits
fm (resize-robust) 192 ~36 dB ±35% resize, PNG/JPEG q≥75

Video watermarking

Each video is processed frame by frame. Every Nth frame (frame_stride, default 5) receives the same DWT-QIM watermark with the same clawid UUID. Detection samples up to 10 frames and uses majority vote — detection succeeds as long as at least one watermarked frame survives.


Docker

docker compose up
# API available at http://localhost:8000

Development

git clone https://github.com/Hawky-ai/clawID
cd clawid
pip install -e ".[dev,api,video]"
pytest

Links

PyPI https://pypi.org/project/clawid/
GitHub https://github.com/Hawky-ai/clawID
Hugging Face https://huggingface.co/spaces/Hawky-ai/clawID
hawky.ai https://hawky.ai

License

MIT — Copyright © 2024 hawky.ai

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clawid-0.2.0.tar.gz (37.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clawid-0.2.0-py3-none-any.whl (33.4 kB view details)

Uploaded Python 3

File details

Details for the file clawid-0.2.0.tar.gz.

File metadata

  • Download URL: clawid-0.2.0.tar.gz
  • Upload date:
  • Size: 37.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.2

File hashes

Hashes for clawid-0.2.0.tar.gz
Algorithm Hash digest
SHA256 50852b60253be558f23f85d71e575bcb1490ee427d396acc2b0a5fcea7ef5c22
MD5 c2d273c20b83539c44ebd278764cc966
BLAKE2b-256 064532a4a5cd664eb4c7e8b0a634f1e7ce9c394b252ee960a0f07d0ff78f18ad

See more details on using hashes here.

File details

Details for the file clawid-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: clawid-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.2

File hashes

Hashes for clawid-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ef30ae89463a0c5802e3d776d6aee0d0c1579a9a6f8950a8094379bde9e0855
MD5 1d83fd285e7b844f14c502fb87d58058
BLAKE2b-256 e7d4501ec5adc2166f52ff63537014fcc00f75d4f6840236750f0be61dff5406

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page