Skip to main content

A robust reversible watermarking method that can robustly extract the watermark in lossy channels and perfectly recover both the cover image and the watermark in lossless channels.

Project description

📝 Introduction

CRMark: Cover-Recoverable Watermark, a robust and reversible invisible image watermarking method. CRMark enables perfect reconstruction of the original cover image in lossless channels and robust watermark extraction in lossy channels.

CRMark leverages an Integer Invertible Watermark Network (iIWN) to achieve lossless and invertible mapping between cover-watermark pairs and stego images. It addresses the trade-off between robustness and reversibility in traditional robust reversible watermarking methods, offering significant improvements in robustness, visual quality, and computational efficiency.

Key features:

  • Robustness: Enhanced against distortions through an Encoder-Noise Layer-Decoder framework.
  • Reversibility: Ensures lossless recovery of both the cover image and the watermark in lossless channel.
  • Efficiency: Reduces time complexity and auxiliary bitstream length.

🚀 Usage

pip install crmark

code

import os
import random
import string
import numpy as np
from PIL import Image
from crmark import CRMark

# Create output directory if not exists
os.makedirs("images", exist_ok=True)

# Initialize CRMark in color mode
crmark = CRMark(model_mode="color_256_100", float64=False)


# Generate a random string of length 3 (total 24 bits)
def generate_random_string(n: int) -> str:
    characters = string.ascii_letters + string.digits
    return ''.join(random.choices(characters, k=n))


# Random string message
str_data = generate_random_string(7)
print(str_data)

# Define image paths
cover_path = "crmark/compressor/images/color_cover.png"
rec_cover_path = "images/rec_color_cover.png"
stego_path_clean = "images/color_stego_clean.png"
stego_path_attacked = "images/color_stego_attacked.png"

# === Case 1: Without attack ===
# Encode string into image
success, stego_image = crmark.encode(cover_path, str_data)
stego_image.save(stego_path_clean)

# Recover cover and message from clean image
is_attacked_clean, rec_cover_clean, rec_message_clean = crmark.recover(stego_path_clean)
is_decoded, extracted_message_clean = crmark.decode(stego_path_clean)
rec_cover_clean.save(rec_cover_path)

# Compute pixel difference between original and recovered cover
cover = np.float32(Image.open(cover_path))
rec_clean = np.float32(rec_cover_clean)
diff_clean = np.sum(np.abs(cover - rec_clean))

# === Case 2: With attack ===
# Slightly modify the image to simulate attack
stego = np.float32(Image.open(stego_path_clean))
H, W, C = stego.shape
rand_y = random.randint(0, H - 1)
rand_x = random.randint(0, W - 1)
rand_c = random.randint(0, C - 1)

# Apply a small perturbation (±1)
perturbation = random.choice([-1, 1])
stego[rand_y, rand_x, rand_c] = np.clip(stego[rand_y, rand_x, rand_c] + perturbation, 0, 255)
Image.fromarray(np.uint8(stego)).save(stego_path_attacked)

# Recover from attacked image
is_attacked, rec_cover_attacked, rec_message_attacked = crmark.recover(stego_path_attacked)
is_attacked_flag, extracted_message_attacked = crmark.decode(stego_path_attacked)

rec_attacked = np.float32(rec_cover_attacked)
diff_attacked = np.sum(np.abs(cover - rec_attacked))

# === Print results ===
print("=== Without Attack ===")
print("Original Message:", str_data)
print("Recovered Message:", rec_message_clean)
print("Extracted Message:", extracted_message_clean)
print("Is Attacked:", is_attacked_clean)
print("L1 Pixel Difference:", diff_clean)

print("\n=== With Attack ===")
print("Recovered Message:", rec_message_attacked)
print("Extracted Message:", extracted_message_attacked)
print("Is Attacked:", is_attacked)
print("L1 Pixel Difference:", diff_attacked)

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

crmark-0.0.1.tar.gz (42.1 kB view details)

Uploaded Source

Built Distribution

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

crmark-0.0.1-py3-none-any.whl (43.1 kB view details)

Uploaded Python 3

File details

Details for the file crmark-0.0.1.tar.gz.

File metadata

  • Download URL: crmark-0.0.1.tar.gz
  • Upload date:
  • Size: 42.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.9.19

File hashes

Hashes for crmark-0.0.1.tar.gz
Algorithm Hash digest
SHA256 14a3d2e253f31e2fd2bbf7512c9d430500149204fbe1b564fb647abb3735471a
MD5 088d319034d93a85d4c4aaf5e2d5eb69
BLAKE2b-256 b4939862aa14167811d59acbf66a2c0e4baefd20c0624edd3dc97a29cbfd7936

See more details on using hashes here.

File details

Details for the file crmark-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: crmark-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 43.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.9.19

File hashes

Hashes for crmark-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3137ea5e9240a0b3ff8872ada5a6196761e1c1e3da86904553276848e0381b7e
MD5 178613a97db8c3c99c3f3e73b9c171c2
BLAKE2b-256 54be02f8f6c8dae4c5a55e6c01cda304d8ec0d3e7dac06d498561234cac42e17

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