-
Notifications
You must be signed in to change notification settings - Fork 150
API
invisible-watermark is a python library and command line tool for creating invisible watermark over image.(aka. blink image watermark, digital image watermark). The algorithm doesn't reply 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 library supports 3 internal algorithms now:
- two are Discrete wavelet transform + Discrete cosine transform frequency embedding algorithm variants.
- The other one is RivaGAN, a deep-learning model trained from Hollywood2 movie clips dataset.
But only the default method (dwtDCT, ~300ms 1080P image) is suitable for on-the-fly embedding. The other methods are too slow on a CPU only environment.
- dwtDct: YUV Space U Frame -> 2 level DWT -> 4x4 Block -> DCT -> embed watermark bit into max non trivial decomposition.
- dwtDctSvd: YUV Space U Frame -> 1 level DWT -> 4x4 Block -> DCT -> SVD -> embed watermark bit into first decomposition of singular value.
- rivaGan: encoder/decoder model with Attention mechanism + embed watermark bits into vector.
pip install invisible-watermark
from imwatermark import WatermarkEncoder
If you don't use rivaGan, you can skip it.
WatermarkEncoder.loadModel()
- bytes encoding bits length = 8 * bytes length
encoder = WatermarkEncoder()
encoder.set_watermark('bytes', 'test'.encode('utf-8'))
- uuid encoding bits length = 128
import uuid
uuid = str(uuid.uuid4())
encoder.set_watermark('uuid', uuid)
- ipv4 encoding bits length = 32
encoder.set_watermark('ipv4', '192.168.0.1')
- b16 encoding bits length = 4 * b16 bytes length
# 'test' b16 expression, should be bytes type
b16 = b'74657374'
encoder.set_watermark('b16', b16)
- bits encoding bits length = array length
bits = [1,1,0,0,0,0,1,1]
encoder.set_watermark('bits', bits)
"""
cv2Image: cv2Image is numpy array (3 channels), returned by cv2.imread(inputFile)
method: dwtDct | dwtDctSvd | rivaGan
"""
encode(cv2Image, method='dwtDct')
Note: RivaGan model only supports embedding 32 bits watermark. 64 bits model is still on the way.
For other methods we suggest you embed a 64 bits id as watermark.
- example embed 4 characters (32 bits) watermark
import cv2
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)
from imwatermark import WatermarkDecoder
If you don't use rivaGan, you can skip it.
WatermarkDecoder.loadModel()
"""
wmType: bytes | bits | b16 | uuid | ipv4
bitLength: encoding watermark bits length
"""
decoder = WatermarkDecoder(wmType, bitsLength)
"""
cv2Image: 3 channel numpy array, returned by cv2.imread
method: dwtDct | dwtDctSvd | rivaGan
return value:
- If wmType = bytes|b16, return watermark bytes
- If wmType = uuid|ipv4, return string
- If wmType = bits, return a list of 0/1
"""
watermark = decoder.decode(cv2Image, method)
- example decode 4 characters (32 bits) watermark
import cv2
bgr = cv2.imread('test_wm.png')
decoder = WatermarkDecoder('bytes', 32)
watermark = decoder.decode(bgr, 'dwtDct')
print(watermark.decode('utf-8'))
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]