Metadata-Version: 2.4
Name: latseal
Version: 1.1.0
Summary: LatentSeal watermarking utilities and text autoencoder packaged for Python.
Author: IMATAG
License-Expression: BSD-3-Clause-Attribution
Project-URL: Homepage, https://github.com/gautierevn/latentseal
Project-URL: Repository, https://github.com/gautierevn/latentseal
Project-URL: Issues, https://github.com/gautierevn/latentseal/issues
Project-URL: Models, https://huggingface.co/Gevennou/lseal
Keywords: watermarking,vision,nlp,torch
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch>=2.2
Requires-Dist: torchvision>=0.17
Requires-Dist: numpy>=1.24
Requires-Dist: Pillow>=9.0
Requires-Dist: transformers>=4.51.3
Requires-Dist: huggingface-hub>=0.20
Requires-Dist: scipy>=1.10
Requires-Dist: peft<1.0,>=0.12
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Dynamic: license-file

# LatentSeal

Fast, secure & high‑capacity **semantic image watermarking** with text‑autoencoded messages.

> Hide full sentences in images, survive heavy JPEG/crop/noise, decode in real time.

## Installation

```bash
pip install latseal  # use `pip install -e .` when developing locally
```

The first call to `latseal.embed(...)` or `latseal.encode(...)` will download
the required TorchScript models, autoencoder checkpoint and tokenizer into
`~/.cache/latseal` (override with `LATSEAL_CACHE_DIR`). The download is ~1.6 GB
and only happens once per machine. Set `LATSEAL_LOCAL_ONLY=1` to disable
network access and rely on locally provided weights via the `LATSEAL_*`
environment overrides documented in `latseal._resources`. By default the assets
are pulled from the Hugging Face repository [`Gevennou/lseal`](https://huggingface.co/Gevennou/lseal).


Watermarking and autoencoding can be used independently or chained, depending
on your workflow.

## Quickstart Demo

Watermarking and text autoencoding demonstrated separately (requires the
`requests` package):

```python
from pathlib import Path

import requests
import torch
from PIL import Image
import latseal


img_url = "https://images.dog.ceo/breeds/frise-bichon/3.jpg"  # 640x640 image
img_path = Path("latseal_demo_input.jpg")
secret_key = "demo-secret"
text_payload = (
    "Close-up photograph of a gourmet grilled cheese sandwich that has been artistically sliced in half. Each half reveals a gooey, white cheese center ith an enticing stringy, melted cheese bridge connecting them. The sandwich features double"
)

response = requests.get(img_url, timeout=30)
response.raise_for_status()
img_path.write_bytes(response.content)
image = Image.open(img_path).convert("RGB")

# --- Watermark round-trip ---
message = latseal.random_message()
secret_message = latseal.secret_rotation(message, secret_key=secret_key)
wm_image = latseal.embed(secret_message, image, secret_key=None)
wm_image.save("latseal_demo_watermarked.jpg")

recovered = latseal.detect(wm_image, secret_key=None)
recovered = latseal.secret_rotation(recovered, secret_key=secret_key, inverse=True)

cos_sim = torch.dot(message, recovered) / (message.norm() * recovered.norm())
print(f"Cosine similarity between original and recovered message: {float(cos_sim):.4f}")

# --- Text autoencoder round-trip ---
latent = latseal.encode(text_payload)
decoded = latseal.decode(latent)
score = latseal.confidence(latent)

print(f"Original text: {text_payload}")
print(f"Decoded text : {decoded}")
print(f"Confidence    : {score:.3f}")
```

## All-in-One Text Latent Demo

Prefer to hide a specific sentence directly? Encode it, embed the latent, and
report fidelity metrics (requires the `requests` and `numpy` packages):

```python
from pathlib import Path

import requests
import torch
from PIL import Image
import latseal
import numpy as np


def psnr(img_a, img_b, max_val=255.0):
    """PSNR in dB for 8-bit RGB PIL images."""
    a = np.asarray(img_a, dtype=np.float32)
    b = np.asarray(img_b, dtype=np.float32)
    mse = np.mean((a - b) ** 2)
    if mse == 0:
        return float("inf")
    return 20 * np.log10(max_val) - 10 * np.log10(mse)


img_url = "https://images.dog.ceo/breeds/frise-bichon/3.jpg"  # 640x640 image
img_path = Path("latseal_demo_psnr_input.jpg")
secret_key = "demo-secret"
text_payload = (
    "Close-up photograph of a gourmet grilled cheese sandwich that has been artistically sliced in half. Each half reveals a gooey, white cheese center with an enticing stringy, melted cheese bridge connecting them. The sandwich features double"
)

response = requests.get(img_url, timeout=30)
response.raise_for_status()
img_path.write_bytes(response.content)
image = Image.open(img_path).convert("RGB")

latent_message = latseal.encode(text_payload).squeeze(0)
secret_message = latseal.secret_rotation(latent_message, secret_key=secret_key)
wm_image = latseal.embed(secret_message, image, secret_key=None)
wm_image.save("latseal_text_latent_watermarked.jpg")

detected = latseal.detect(wm_image, secret_key=None)
detected = latseal.secret_rotation(detected, secret_key=secret_key, inverse=True).squeeze(0)

print(f"PSNR: {psnr(image, wm_image):.2f} dB")
cos_sim = torch.dot(latent_message, detected) / (latent_message.norm() * detected.norm())
print(f"Cosine similarity: {float(cos_sim):.4f}")
print(f"Decoded text: {latseal.decode(detected)}")
print(f"Confidence: {latseal.confidence(detected)}")
```

## Features
* **Content‑aware payload** – 256‑D unit‑norm latent vectors from a lightweight text autoencoder (TAE).
* **Robust embedding** – finetuned watermark model plus a secret invertible rotation (“spin”) boosts security.
* **High capacity** – > 256 bits (full sentences) per image.
* **Confidence score** – flags unreliable extractions via the confidence metric.


## License
BSD-3-Clause-Attribution — see `LICENSE`.
