The library for creating and decoding invisible image watermarks
invisible-watermark 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 still experimental and it doesn't support GPU acceleration, carefully deploy it on the production environment. The default method dwtDCT(one variant of frequency methods) is ready for on-the-fly embedding, the other methods are too slow on a CPU only environment.
dwtDct
is fast and suitable for on-the-fly embeddingdwtDctSvd
is 3x slower and rivaGan
is 10x slower, for large image they are not suitable for on-the-fly embeddingaccuracy
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
background:
- Discrete wavelet transform
- Discrete cosine transform.
- RivaGAN, a deep-learning model trained from Hollywood2 movie clips dataset.
pip install invisible-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)
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'))
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)
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 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
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 |
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 |
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]