Package: invisible-watermark-gpu
invisible-watermark-gpuinvisible-watermark-gpuis apythonlibrary 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 thatthis library is adapted frominvisible-watermarkin an attempt to optimize the performance and accuracy of a few of the algorithms.InstallationIt'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/exportPYCUDWT_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 A100moduleloadcuda/12.1exportLD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda/lib64exportCUDA_PATH=/usr/local/cudaexportPYCUDWT_CC=80exportCUDAHOME=/usr/local/cuda-12.1# install !pipinstallinvisible-watermark-gpu--no-cache-dirYou 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-mpytest-k'test_pycudwt_installed_correctly'Once that works, you should be off to the races!ALgorithmssupported algorithmsDiscrete wavelet transform+Discrete cosine transformfrequency embedding algorithm variants.RivaGAN, a deep-learning model trained from Hollywood2 movie clips dataset.speeddefault embedding methoddwtDctis fast and suitable for on-the-fly embeddingdwtDctSvdis 3x slower andrivaGanis 10x slower, for large image they are not suitable for on-the-fly embeddingaccuracyThe algorithmcannot guaranteeto 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 colorSupported Algorithmsfrequency methodsdwtDct: DWT + DCT transform, embed watermark bit into max non-trivial coefficient of block dct coefficentsdwtDctSvd: DWT + DCT transform, SVD decomposition of each block, embed watermark bit into singular value decompositionrivaGan: encoder/decoder model with Attention mechanism + embed watermark bits into vector.background:Discrete wavelet transformDiscrete cosine transform.RivaGAN, a deep-learning model trained from Hollywood2 movie clips dataset.Library APIEmbed watermarkexampleembed 4 characters (32 bits) watermarkimportcv2fromimwatermarkimportWatermarkEncoderbgr=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:fromimwatermarkimportWatermarkEncoder# only supported for method "dwtDct" currentlyWatermarkEncoder().warmup_gpu()Decode watermarkexampledecode 4 characters (32 bits) watermarkimportcv2fromimwatermarkimportWatermarkDecoderbgr=cv2.imread('test_wm.png')decoder=WatermarkDecoder('bytes',32)watermark=decoder.decode(bgr,'dwtDct')print(watermark.decode('utf-8'))CLI Usageembed 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 ResultFor better doc reading, we compress all images in this page, but the test is taken on 1920x1080 original image.Methods are not robust toresizeor aspect ratio changedcropbut robust tonoise,color filter,brightnessandjpg compress.rivaGan outperforms the default method on crop attack.only default method is ready for on-the-fly embedding.InputInput Image: 1960x1080 ImageWatermark: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=36Attack PerformanceWatermarked ImageAttacksImageFreq MethodRivaGanJPG CompressPassPassNoisePassPassBrightnessPassPassOverlayPassPassMaskPassPasscrop 7x5FailPassResize 50%FailFailRotate 30 degressFailFailRunning Speed (CPU Only)ImageMethodEncodingDecoding1920x1080dwtDct300-350ms150ms-200ms1920x1080dwtDctSvd1500ms-2s~1s1920x1080rivaGan~5s4-5s600x600dwtDct70ms60ms600x600dwtDctSvd185ms320ms600x600rivaGan1s600msRunning Speed (GPU Only)TODO: fill this in!RivaGAN ExperimentalFurther, We will deliver the 64bit rivaGan model and test the performance on GPU environment.Detail:https://github.com/DAI-Lab/RivaGANZhang, Kevin Alex and Xu, Lei and Cuesta-Infante, Alfredo and Veeramachaneni, Kalyan. Robust Invisible Video Watermarking with Attention. MIT EECS, September 2019.[PDF]