├── ori.png ├── res.png ├── extract.png ├── watermark.png ├── README.md ├── LICENSE ├── decode.py └── encode.py /ori.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyacool/blind-watermark/HEAD/ori.png -------------------------------------------------------------------------------- /res.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyacool/blind-watermark/HEAD/res.png -------------------------------------------------------------------------------- /extract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyacool/blind-watermark/HEAD/extract.png -------------------------------------------------------------------------------- /watermark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyacool/blind-watermark/HEAD/watermark.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blind-watermark 2 | This was written in Python2.7 3 | [Python3 Version](https://github.com/linyacool/blind-watermark/tree/python3) 4 | # Usage 5 | ```shell 6 | python encode.py --image --watermark --result 7 | 8 | python decode.py --original --image --result 9 | 10 | Use --alpha to change the alpha (default 5.0). 11 | ``` 12 | # Example 13 | ## encode: 14 | original image
15 | ![image](https://github.com/linyacool/blind-watermark/blob/master/ori.png) 16 | 17 | watermark
18 | ![image](https://github.com/linyacool/blind-watermark/blob/master/watermark.png) 19 | 20 | 21 | ```shell 22 | python encode.py --image ori.png --watermark watermark.png --result res.png 23 | ``` 24 | result
25 | ![image](https://github.com/linyacool/blind-watermark/blob/master/res.png) 26 | 27 | ## decode: 28 | ```shell 29 | python decode.py --original ori.png --image res.png --result extract.png 30 | ``` 31 | watermark
32 | ![image](https://github.com/linyacool/blind-watermark/blob/master/extract.png) 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /decode.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import cv2 3 | import numpy as np 4 | import random 5 | import os 6 | from argparse import ArgumentParser 7 | ALPHA = 5 8 | 9 | 10 | def build_parser(): 11 | parser = ArgumentParser() 12 | parser.add_argument('--original', dest='ori', required=True) 13 | parser.add_argument('--image', dest='img', required=True) 14 | parser.add_argument('--result', dest='res', required=True) 15 | parser.add_argument('--alpha', dest='alpha', default=ALPHA) 16 | return parser 17 | 18 | 19 | def main(): 20 | parser = build_parser() 21 | options = parser.parse_args() 22 | ori = options.ori 23 | img = options.img 24 | res = options.res 25 | alpha = float(options.alpha) 26 | if not os.path.isfile(ori): 27 | parser.error("original image %s does not exist." % ori) 28 | if not os.path.isfile(img): 29 | parser.error("image %s does not exist." % img) 30 | decode(ori, img, res, alpha) 31 | 32 | 33 | def decode(ori_path, img_path, res_path, alpha): 34 | ori = cv2.imread(ori_path) 35 | img = cv2.imread(img_path) 36 | ori_f = np.fft.fft2(ori) 37 | img_f = np.fft.fft2(img) 38 | height, width = ori.shape[0], ori.shape[1] 39 | watermark = (ori_f - img_f) / alpha 40 | watermark = np.real(watermark) 41 | res = np.zeros(watermark.shape) 42 | random.seed(height + width) 43 | x = range(height / 2) 44 | y = range(width) 45 | random.shuffle(x) 46 | random.shuffle(y) 47 | for i in range(height / 2): 48 | for j in range(width): 49 | res[x[i]][y[j]] = watermark[i][j] 50 | cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /encode.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import cv2 3 | import numpy as np 4 | import random 5 | import os 6 | from argparse import ArgumentParser 7 | ALPHA = 5 8 | 9 | 10 | def build_parser(): 11 | parser = ArgumentParser() 12 | parser.add_argument('--image', dest='img', required=True) 13 | parser.add_argument('--watermark', dest='wm', required=True) 14 | parser.add_argument('--result', dest='res', required=True) 15 | parser.add_argument('--alpha', dest='alpha', default=ALPHA) 16 | return parser 17 | 18 | 19 | def main(): 20 | parser = build_parser() 21 | options = parser.parse_args() 22 | img = options.img 23 | wm = options.wm 24 | res = options.res 25 | alpha = float(options.alpha) 26 | if not os.path.isfile(img): 27 | parser.error("image %s does not exist." % img) 28 | if not os.path.isfile(wm): 29 | parser.error("watermark %s does not exist." % wm) 30 | encode(img, wm, res, alpha) 31 | 32 | 33 | def encode(img_path, wm_path, res_path, alpha): 34 | img = cv2.imread(img_path) 35 | img_f = np.fft.fft2(img) 36 | height, width, channel = np.shape(img) 37 | watermark = cv2.imread(wm_path) 38 | wm_height, wm_width = watermark.shape[0], watermark.shape[1] 39 | x, y = range(height / 2), range(width) 40 | random.seed(height + width) 41 | random.shuffle(x) 42 | random.shuffle(y) 43 | tmp = np.zeros(img.shape) 44 | for i in range(height / 2): 45 | for j in range(width): 46 | if x[i] < wm_height and y[j] < wm_width: 47 | tmp[i][j] = watermark[x[i]][y[j]] 48 | tmp[height - 1 - i][width - 1 - j] = tmp[i][j] 49 | res_f = img_f + alpha * tmp 50 | res = np.fft.ifft2(res_f) 51 | res = np.real(res) 52 | cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) 53 | if __name__ == '__main__': 54 | main() 55 | --------------------------------------------------------------------------------