GPU adaptation for the library for creating and decoding invisible image watermarks
Project description
invisible-watermark-gpu
invisible-watermark-gpu
is a python library and command line tool for creating invisible watermark over image (a.k.a. blink image watermark, digital image watermark). The algorithm doesn't rely on the original image.
Note that this library is adapted from invisible-watermark
in an attempt to optimize the performance and accuracy of a few of the algorithms.
Installation
It's a little more complex than the CPU-only version since we need to make sure we can link to the proper CUDA libraries.
# find your GPU's gencode here, and set the PYCUDWT_CC environment variable to it
# for example, for an A100, it would be "80" for SM80:
# https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/
export PYCUDWT_CC=80
# also, load your CUDA version and set any and all needed environment variables. this might
# depend on your CUDA version + GPU type. I'm using CUDA 12.1 on an A100
module load cuda/12.1
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda/lib64
export CUDA_PATH=/usr/local/cuda
export PYCUDWT_CC=80
export CUDAHOME=/usr/local/cuda-12.1
# install !
pip install invisible-watermark-gpu --no-cache-dir
You should NOT proceed until this test passes:
# without this test passing, your pycudwt package will NOT work properly, and it will
# only output zeros, silently causing you to not be able to decode anything!
python -m pytest -k 'test_pycudwt_installed_correctly'
Once that works, you should be off to the races!
ALgorithms
- Discrete wavelet transform + Discrete cosine transform frequency embedding algorithm variants.
- RivaGAN, a deep-learning model trained from Hollywood2 movie clips dataset.
- default embedding method
dwtDct
is fast and suitable for on-the-fly embedding dwtDctSvd
is 3x slower andrivaGan
is 10x slower, for large image they are not suitable for on-the-fly embedding
accuracy
- The algorithm cannot guarantee to decode the original watermarks 100% accurately even though we don't apply any attack.
- Known defects: Test shows all algorithms do not perform well for web page screenshots or posters with homogenous background color
Supported Algorithms
dwtDct: DWT + DCT transform, embed watermark bit into max non-trivial coefficient of block dct coefficents
dwtDctSvd: DWT + DCT transform, SVD decomposition of each block, embed watermark bit into singular value decomposition
- rivaGan: encoder/decoder model with Attention mechanism + embed watermark bits into vector.
background:
- Discrete wavelet transform
- Discrete cosine transform.
- RivaGAN, a deep-learning model trained from Hollywood2 movie clips dataset.
Library API
Embed watermark
- example embed 4 characters (32 bits) watermark
import cv2
from imwatermark import WatermarkEncoder
bgr = cv2.imread('test.png')
wm = 'test'
encoder = WatermarkEncoder()
encoder.set_watermark('bytes', wm.encode('utf-8'))
bgr_encoded = encoder.encode(bgr, 'dwtDct')
cv2.imwrite('test_wm.png', bgr_encoded)
Note that if you want to avoid the cold start problem of loading CUDA libraries, you'll need to warmup the GPU first. You can do this by running the following code before you start encoding images:
from imwatermark import WatermarkEncoder
# only supported for method "dwtDct" currently
WatermarkEncoder().warmup_gpu()
Decode watermark
- example decode 4 characters (32 bits) watermark
import cv2
from imwatermark import WatermarkDecoder
bgr = cv2.imread('test_wm.png')
decoder = WatermarkDecoder('bytes', 32)
watermark = decoder.decode(bgr, 'dwtDct')
print(watermark.decode('utf-8'))
CLI Usage
embed watermark: ./invisible-watermark -v -a encode -t bytes -m dwtDct -w 'hello' -o ./test_vectors/wm.png ./test_vectors/original.jpg
decode watermark: ./invisible-watermark -v -a decode -t bytes -m dwtDct -l 40 ./test_vectors/wm.png
positional arguments:
input The path of input
optional arguments:
-h, --help show this help message and exit
-a ACTION, --action ACTION
encode|decode (default: None)
-t TYPE, --type TYPE bytes|b16|bits|uuid|ipv4 (default: bits)
-m METHOD, --method METHOD
dwtDct|dwtDctSvd|rivaGan (default: maxDct)
-w WATERMARK, --watermark WATERMARK
embedded string (default: )
-l LENGTH, --length LENGTH
watermark bits length, required for bytes|b16|bits
watermark (default: 0)
-o OUTPUT, --output OUTPUT
The path of output (default: None)
-v, --verbose print info (default: False)
Test Result
For better doc reading, we compress all images in this page, but the test is taken on 1920x1080 original image.
Methods are not robust to resize or aspect ratio changed crop but robust to noise, color filter, brightness and jpg compress.
rivaGan outperforms the default method on crop attack.
only default method is ready for on-the-fly embedding.
Input
- Input Image: 1960x1080 Image
- Watermark:
- For freq method, we use 64bits, string expression "qingquan"
- For RivaGan method, we use 32bits, string expression "qing"
- Parameters: only take U frame to keep image quality,
scale=36
Attack Performance
Watermarked Image
Attacks | Image | Freq Method | RivaGan |
---|---|---|---|
JPG Compress | Pass | Pass | |
Noise | Pass | Pass | |
Brightness | Pass | Pass | |
Overlay | Pass | Pass | |
Mask | Pass | Pass | |
crop 7x5 | Fail | Pass | |
Resize 50% | Fail | Fail | |
Rotate 30 degress | Fail | Fail |
Running Speed (CPU Only)
Image | Method | Encoding | Decoding |
---|---|---|---|
1920x1080 | dwtDct | 300-350ms | 150ms-200ms |
1920x1080 | dwtDctSvd | 1500ms-2s | ~1s |
1920x1080 | rivaGan | ~5s | 4-5s |
600x600 | dwtDct | 70ms | 60ms |
600x600 | dwtDctSvd | 185ms | 320ms |
600x600 | rivaGan | 1s | 600ms |
Running Speed (GPU Only)
TODO: fill this in!
RivaGAN Experimental
Further, We will deliver the 64bit rivaGan model and test the performance on GPU environment.
Detail: https://github.com/DAI-Lab/RivaGAN
Zhang, Kevin Alex and Xu, Lei and Cuesta-Infante, Alfredo and Veeramachaneni, Kalyan. Robust Invisible Video Watermarking with Attention. MIT EECS, September 2019.[PDF]
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
Built Distribution
Hashes for invisible-watermark-gpu-0.2.2.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6182486b5e8de0e845144ccc4672c3045c8a961aca3f4cca933abca03ad5cefd |
|
MD5 | 29fa25fcfdd50c850b486fd08dd42b10 |
|
BLAKE2b-256 | cdc5fd8167f44facab00c20284bdefe0b07d2ec9ae5dec9f2fcc3ff49e1df6ba |
Hashes for invisible_watermark_gpu-0.2.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 37f1eea23025578fd800ddc54bddbc682afa5e1a50c00ac55e9e052a63f9f73c |
|
MD5 | 43f5c822917ea66e64257103c0486bbc |
|
BLAKE2b-256 | 624f5c9a20cf2dcb1b4dfc7accad02b805e413d19bd5ea412b406336292a2f6a |