Showing preview only (863K chars total). Download the full file or copy to clipboard to get everything.
Repository: guofei9987/blind_watermark
Branch: master
Commit: 322c90dc02d4
Files: 39
Total size: 836.4 KB
Directory structure:
gitextract_0vkho7vc/
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── tests.yml
├── .travis.yml
├── LICENSE
├── README.md
├── README_cn.md
├── blind_watermark/
│ ├── __init__.py
│ ├── att.py
│ ├── blind_watermark.py
│ ├── bwm_core.py
│ ├── cli_tools.py
│ ├── pool.py
│ ├── recover.py
│ ├── requirements.txt
│ └── version.py
├── docs/
│ ├── .nojekyll
│ ├── README.md
│ ├── _coverpage.md
│ ├── _navbar.md
│ ├── _sidebar.md
│ ├── en/
│ │ ├── README.md
│ │ ├── _coverpage.md
│ │ └── _sidebar.md
│ ├── index.html
│ ├── make_doc.py
│ ├── run_server.bat
│ ├── vue.css
│ └── zh/
│ ├── README.md
│ ├── _coverpage.md
│ └── _sidebar.md
├── examples/
│ ├── example_bit.py
│ ├── example_demo.ipynb
│ ├── example_img.py
│ ├── example_no_writing.py
│ ├── example_str.py
│ ├── example_str_multi.py
│ └── output/
│ └── .keep
├── requirements.txt
└── setup.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
custom: ["https://www.guofei.site/微信打赏.jpg"]
open_collective: blind_watermark # Replace with a single Open Collective username
================================================
FILE: .github/workflows/tests.yml
================================================
name: test all
on: [ push, pull_request ]
jobs:
build:
runs-on: ubuntu-latest
name: Test python API
defaults:
run:
working-directory: .
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install requirements
run: |
pip install -r requirements.txt
# pip install pytest-cover
- name: Run tests
run: |
python setup.py install
python examples/example_bit.py
python examples/example_img.py
python examples/example_no_writing.py
python examples/example_str.py
python examples/example_str_multi.py
# pytest --cov .
# - name: Upload coverage reports to Codecov with GitHub Action
# uses: codecov/codecov-action@v3
================================================
FILE: .travis.yml
================================================
language: python
python:
- "3.8"
# command to install dependencies
install:
- pip install -r requirements.txt
- pip install numpy==1.18.1
- pip install coverage codecov
- python setup.py install
# command to run tests
script:
- cd examples
- coverage run -p example_no_writing.py
- coverage run -p example_bit.py
- coverage run -p example_str.py
- coverage run -p example_img.py
- cp .coverage.* ..
- cd ..
# Push the results back to codecov
after_success:
- coverage combine
- codecov
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 郭飞
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# blind-watermark
Blind watermark based on DWT-DCT-SVD.
[](https://pypi.org/project/blind_watermark/)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://github.com/guofei9987/blind_watermark/blob/master/LICENSE)


[](https://github.com/guofei9987/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/fork)
[](https://pepy.tech/project/blind-watermark)
[](https://github.com/guofei9987/blind_watermark/discussions)
<a href="https://hellogithub.com/repository/guofei9987/blind_watermark" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=3834302ff46a40f188a651ef8bd26ff5&claim_uid=se0WHo8cbiLv2w1&theme=small" alt="Featured|HelloGitHub" /></a>
- **Documentation:** [https://BlindWatermark.github.io/blind_watermark/#/en/](https://BlindWatermark.github.io/blind_watermark/#/en/)
- **文档:** [https://BlindWatermark.github.io/blind_watermark/#/zh/](https://BlindWatermark.github.io/blind_watermark/#/zh/)
- **中文 readme** [README_cn.md](README_cn.md)
- **Source code:** [https://github.com/guofei9987/blind_watermark](https://github.com/guofei9987/blind_watermark)
# install
```bash
pip install blind-watermark
```
For the current developer version:
```bach
git clone git@github.com:guofei9987/blind_watermark.git
cd blind_watermark
pip install .
```
# How to use
## Use in bash
```bash
# embed watermark into image:
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
# extract watermark from image:
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
```
## Use in Python
Original Image + Watermark = Watermarked Image
 + '@guofei9987 开源万岁!' = 
See the [codes](/examples/example_str.py)
Embed watermark:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_img('pic/ori_img.jpg')
wm = '@guofei9987 开源万岁!'
bwm1.read_wm(wm, mode='str')
bwm1.embed('output/embedded.png')
len_wm = len(bwm1.wm_bit)
print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))
```
Extract watermark:
```python
bwm1 = WaterMark(password_img=1, password_wm=1)
wm_extract = bwm1.extract('output/embedded.png', wm_shape=len_wm, mode='str')
print(wm_extract)
```
Output:
>@guofei9987 开源万岁!
### attacks on Watermarked Image
|attack method|image after attack|extracted watermark|
|--|--|--|
|Rotate 45 Degrees||'@guofei9987 开源万岁!'|
|Random crop||'@guofei9987 开源万岁!'|
|Masks|  |'@guofei9987 开源万岁!'|
|Vertical cut||'@guofei9987 开源万岁!'|
|Horizontal cut||'@guofei9987 开源万岁!'|
|Resize||'@guofei9987 开源万岁!'|
|Pepper Noise||'@guofei9987 开源万岁!'|
|Brightness 10% Down||'@guofei9987 开源万岁!'|
### embed images
embed watermark:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_wm=1, password_img=1)
# read original image
bwm1.read_img('pic/ori_img.jpg')
# read watermark
bwm1.read_wm('pic/watermark.png')
# embed
bwm1.embed('output/embedded.png')
```
Extract watermark:
```python
bwm1 = WaterMark(password_wm=1, password_img=1)
# notice that wm_shape is necessary
bwm1.extract(filename='output/embedded.png', wm_shape=(128, 128), out_wm_name='output/extracted.png', )
```
|attack method|image after attack|extracted watermark|
|--|--|--|
|Rotate 45 Degrees|||
|Random crop|||
|Mask|  ||
### embed array of bits
See it [here](/examples/example_bit.py)
As demo, we embed 6 bytes data:
```python
wm = [True, False, True, True, True, False]
```
Embed:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_ori_img('pic/ori_img.jpg')
bwm1.read_wm([True, False, True, True, True, False], mode='bit')
bwm1.embed('output/embedded.png')
```
Extract:
```python
bwm1 = WaterMark(password_img=1, password_wm=1, wm_shape=6)
wm_extract = bwm1.extract('output/打上水印的图.png', mode='bit')
print(wm_extract)
```
Notice that `wm_shape` (shape of watermark) is necessary
The output `wm_extract` is an array of float. set a threshold such as 0.5.
# Concurrency
```python
WaterMark(..., processes=None)
```
- `processes` number of processes, can be integer. Default `None`, which means using all processes.
## Related Project
- text_blind_watermark (Embed message into text): [https://github.com/guofei9987/text_blind_watermark](https://github.com/guofei9987/text_blind_watermark)
- HideInfo(hide as image, hide as sounds, hide as text):[https://github.com/guofei9987/HideInfo](https://github.com/guofei9987/HideInfo)
================================================
FILE: README_cn.md
================================================
# blind-watermark
基于频域的数字盲水印
[](https://pypi.org/project/blind_watermark/)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://github.com/guofei9987/blind_watermark/blob/master/LICENSE)


[](https://github.com/guofei9987/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/fork)
[](https://pepy.tech/project/blind-watermark)
[](https://github.com/guofei9987/blind_watermark/discussions)
- **Documentation:** [https://BlindWatermark.github.io/blind_watermark/#/en/](https://BlindWatermark.github.io/blind_watermark/#/en/)
- **文档:** [https://BlindWatermark.github.io/blind_watermark/#/zh/](https://BlindWatermark.github.io/blind_watermark/#/zh/)
- **English readme** [README.md](README.md)
- **Source code:** [https://github.com/guofei9987/blind_watermark](https://github.com/guofei9987/blind_watermark)
# 安装
```bash
pip install blind-watermark
```
或者安装最新开发版本
```bach
git clone git@github.com:guofei9987/blind_watermark.git
cd blind_watermark
pip install .
```
# 如何使用
## 命令行中使用
```bash
# 嵌入水印:
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
# 提取水印:
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
```
## Python 中使用
原图 + 水印 = 打上水印的图
 + '@guofei9987 开源万岁!' = 
参考 [代码](/examples/example_str.py)
嵌入水印
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_img('pic/ori_img.jpg')
wm = '@guofei9987 开源万岁!'
bwm1.read_wm(wm, mode='str')
bwm1.embed('output/embedded.png')
len_wm = len(bwm1.wm_bit)
print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))
```
提取水印
```python
bwm1 = WaterMark(password_img=1, password_wm=1)
wm_extract = bwm1.extract('output/embedded.png', wm_shape=len_wm, mode='str')
print(wm_extract)
```
Output:
>@guofei9987 开源万岁!
### 各种攻击后的效果
|攻击方式|攻击后的图片|提取的水印|
|--|--|--|
|旋转攻击45度||'@guofei9987 开源万岁!'|
|随机截图||'@guofei9987 开源万岁!'|
|多遮挡|  |'@guofei9987 开源万岁!'|
|纵向裁剪||'@guofei9987 开源万岁!'|
|横向裁剪||'@guofei9987 开源万岁!'|
|缩放攻击||'@guofei9987 开源万岁!'|
|椒盐攻击||'@guofei9987 开源万岁!'|
|亮度攻击||'@guofei9987 开源万岁!'|
### 嵌入图片
参考 [代码](/examples/example_str.py)
嵌入:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_wm=1, password_img=1)
# read original image
bwm1.read_img('pic/ori_img.jpg')
# read watermark
bwm1.read_wm('pic/watermark.png')
# embed
bwm1.embed('output/embedded.png')
```
提取:
```python
bwm1 = WaterMark(password_wm=1, password_img=1)
# notice that wm_shape is necessary
bwm1.extract(filename='output/embedded.png', wm_shape=(128, 128), out_wm_name='output/extracted.png', )
```
|攻击方式|攻击后的图片|提取的水印|
|--|--|--|
|旋转攻击45度|||
|随机截图|||
|多遮挡|  ||
### 隐水印还可以是二进制数据
参考 [代码](/examples/example_bit.py)
作为 demo, 如果要嵌入是如下长度为6的二进制数据
```python
wm = [True, False, True, True, True, False]
```
嵌入水印
```python
# 除了嵌入图片,也可以嵌入比特类数据
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_ori_img('pic/ori_img.jpg')
bwm1.read_wm([True, False, True, True, True, False], mode='bit')
bwm1.embed('output/打上水印的图.png')
```
解水印:(注意设定水印形状 `wm_shape`)
```python
bwm1 = WaterMark(password_img=1, password_wm=1, wm_shape=6)
wm_extract = bwm1.extract('output/打上水印的图.png', mode='bit')
print(wm_extract)
```
解出的水印是一个0~1之间的实数,方便用户自行卡阈值。如果水印信息量远小于图片可容纳量,偏差极小。
# 并行计算
```python
WaterMark(..., processes=None)
```
- `processes`: 整数,指定线程数。默认为 `None`, 表示使用全部线程。
## 相关项目
- text_blind_watermark (文本盲水印,把信息隐秘地打入文本): [https://github.com/guofei9987/text_blind_watermark](https://github.com/guofei9987/text_blind_watermark)
- HideInfo(藏物于图、藏物于音、藏图于文):[https://github.com/guofei9987/HideInfo](https://github.com/guofei9987/HideInfo)
================================================
FILE: blind_watermark/__init__.py
================================================
from .blind_watermark import WaterMark
from .bwm_core import WaterMarkCore
from .att import *
from .recover import recover_crop
from .version import __version__, bw_notes
================================================
FILE: blind_watermark/att.py
================================================
# coding=utf-8
# attack on the watermark
import cv2
import numpy as np
import warnings
def cut_att3(input_filename=None, input_img=None, output_file_name=None, loc_r=None, loc=None, scale=None):
# 剪切攻击 + 缩放攻击
if input_filename:
input_img = cv2.imread(input_filename)
if loc is None:
h, w, _ = input_img.shape
x1, y1, x2, y2 = int(w * loc_r[0][0]), int(h * loc_r[0][1]), int(w * loc_r[1][0]), int(h * loc_r[1][1])
else:
x1, y1, x2, y2 = loc
# 剪切攻击
output_img = input_img[y1:y2, x1:x2].copy()
# 如果缩放攻击
if scale and scale != 1:
h, w, _ = output_img.shape
output_img = cv2.resize(output_img, dsize=(round(w * scale), round(h * scale)))
else:
output_img = output_img
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
cut_att2 = cut_att3
def resize_att(input_filename=None, input_img=None, output_file_name=None, out_shape=(500, 500)):
# 缩放攻击:因为攻击和还原都是缩放,所以攻击和还原都调用这个函数
if input_filename:
input_img = cv2.imread(input_filename)
output_img = cv2.resize(input_img, dsize=out_shape)
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def bright_att(input_filename=None, input_img=None, output_file_name=None, ratio=0.8):
# 亮度调整攻击,ratio应当多于0
# ratio>1是调得更亮,ratio<1是亮度更暗
if input_filename:
input_img = cv2.imread(input_filename)
output_img = input_img * ratio
output_img[output_img > 255] = 255
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def shelter_att(input_filename=None, input_img=None, output_file_name=None, ratio=0.1, n=3):
# 遮挡攻击:遮挡图像中的一部分
# n个遮挡块
# 每个遮挡块所占比例为ratio
if input_filename:
output_img = cv2.imread(input_filename)
else:
output_img = input_img.copy()
input_img_shape = output_img.shape
for i in range(n):
tmp = np.random.rand() * (1 - ratio) # 随机选择一个地方,1-ratio是为了防止溢出
start_height, end_height = int(tmp * input_img_shape[0]), int((tmp + ratio) * input_img_shape[0])
tmp = np.random.rand() * (1 - ratio)
start_width, end_width = int(tmp * input_img_shape[1]), int((tmp + ratio) * input_img_shape[1])
output_img[start_height:end_height, start_width:end_width, :] = 255
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def salt_pepper_att(input_filename=None, input_img=None, output_file_name=None, ratio=0.01):
# 椒盐攻击
if input_filename:
input_img = cv2.imread(input_filename)
input_img_shape = input_img.shape
output_img = input_img.copy()
for i in range(input_img_shape[0]):
for j in range(input_img_shape[1]):
if np.random.rand() < ratio:
output_img[i, j, :] = 255
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def rot_att(input_filename=None, input_img=None, output_file_name=None, angle=45):
# 旋转攻击
if input_filename:
input_img = cv2.imread(input_filename)
rows, cols, _ = input_img.shape
M = cv2.getRotationMatrix2D(center=(cols / 2, rows / 2), angle=angle, scale=1)
output_img = cv2.warpAffine(input_img, M, (cols, rows))
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def cut_att_height(input_filename=None, input_img=None, output_file_name=None, ratio=0.8):
warnings.warn('will be deprecated in the future, use att.cut_att2 instead')
# 纵向剪切攻击
if input_filename:
input_img = cv2.imread(input_filename)
input_img_shape = input_img.shape
height = int(input_img_shape[0] * ratio)
output_img = input_img[:height, :, :]
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def cut_att_width(input_filename=None, input_img=None, output_file_name=None, ratio=0.8):
warnings.warn('will be deprecated in the future, use att.cut_att2 instead')
# 横向裁剪攻击
if input_filename:
input_img = cv2.imread(input_filename)
input_img_shape = input_img.shape
width = int(input_img_shape[1] * ratio)
output_img = input_img[:, :width, :]
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
def cut_att(input_filename=None, output_file_name=None, input_img=None, loc=((0.3, 0.1), (0.7, 0.9)), resize=0.6):
warnings.warn('will be deprecated in the future, use att.cut_att2 instead')
# 截屏攻击 = 裁剪攻击 + 缩放攻击 + 知道攻击参数(按照参数还原)
# 裁剪攻击:其它部分都补0
if input_filename:
input_img = cv2.imread(input_filename)
output_img = input_img.copy()
shape = output_img.shape
x1, y1, x2, y2 = shape[0] * loc[0][0], shape[1] * loc[0][1], shape[0] * loc[1][0], shape[1] * loc[1][1]
output_img[:int(x1), :] = 255
output_img[int(x2):, :] = 255
output_img[:, :int(y1)] = 255
output_img[:, int(y2):] = 255
if resize is not None:
# 缩放一次,然后还原
output_img = cv2.resize(output_img,
dsize=(int(shape[1] * resize), int(shape[0] * resize))
)
output_img = cv2.resize(output_img, dsize=(int(shape[1]), int(shape[0])))
if output_file_name is not None:
cv2.imwrite(output_file_name, output_img)
return output_img
# def cut_att2(input_filename=None, input_img=None, output_file_name=None, loc_r=((0.3, 0.1), (0.9, 0.9)), scale=1.1):
# # 截屏攻击 = 剪切攻击 + 缩放攻击 + 不知道攻击参数
# if input_filename:
# input_img = cv2.imread(input_filename)
# h, w, _ = input_img.shape
# x1, y1, x2, y2 = int(w * loc_r[0][0]), int(h * loc_r[0][1]), int(w * loc_r[1][0]), int(h * loc_r[1][1])
#
# output_img = cut_att3(input_img=input_img, output_file_name=output_file_name,
# loc=(x1, y1, x2, y2), scale=scale)
# return output_img, (x1, y1, x2, y2)
def anti_cut_att_old(input_filename, output_file_name, origin_shape):
warnings.warn('will be deprecated in the future')
# 反裁剪攻击:复制一块范围,然后补全
# origin_shape 分辨率与约定理解的是颠倒的,约定的是列数*行数
input_img = cv2.imread(input_filename)
output_img = input_img.copy()
output_img_shape = output_img.shape
if output_img_shape[0] > origin_shape[0] or output_img_shape[1] > origin_shape[1]:
print('裁剪打击后的图片,不可能比原始图片大,检查一下')
return
# 还原纵向打击
while output_img_shape[0] < origin_shape[0]:
output_img = np.concatenate([output_img, output_img[:origin_shape[0] - output_img_shape[0], :, :]], axis=0)
output_img_shape = output_img.shape
while output_img_shape[1] < origin_shape[1]:
output_img = np.concatenate([output_img, output_img[:, :origin_shape[1] - output_img_shape[1], :]], axis=1)
output_img_shape = output_img.shape
cv2.imwrite(output_file_name, output_img)
def anti_cut_att(input_filename=None, input_img=None, output_file_name=None, origin_shape=None):
warnings.warn('will be deprecated in the future, use att.cut_att2 instead')
# 反裁剪攻击:补0
# origin_shape 分辨率与约定理解的是颠倒的,约定的是列数*行数
if input_filename:
input_img = cv2.imread(input_filename)
output_img = input_img.copy()
output_img_shape = output_img.shape
if output_img_shape[0] > origin_shape[0] or output_img_shape[1] > origin_shape[1]:
print('裁剪打击后的图片,不可能比原始图片大,检查一下')
return
# 还原纵向打击
if output_img_shape[0] < origin_shape[0]:
output_img = np.concatenate(
[output_img, 255 * np.ones((origin_shape[0] - output_img_shape[0], output_img_shape[1], 3))]
, axis=0)
output_img_shape = output_img.shape
if output_img_shape[1] < origin_shape[1]:
output_img = np.concatenate(
[output_img, 255 * np.ones((output_img_shape[0], origin_shape[1] - output_img_shape[1], 3))]
, axis=1)
if output_file_name:
cv2.imwrite(output_file_name, output_img)
return output_img
================================================
FILE: blind_watermark/blind_watermark.py
================================================
#!/usr/bin/env python3
# coding=utf-8
# @Time : 2020/8/13
# @Author : github.com/guofei9987
import warnings
import numpy as np
import cv2
from .bwm_core import WaterMarkCore
from .version import bw_notes
class WaterMark:
def __init__(self, password_wm=1, password_img=1, block_shape=(4, 4), mode='common', processes=None):
bw_notes.print_notes()
self.bwm_core = WaterMarkCore(password_img=password_img, mode=mode, processes=processes)
self.password_wm = password_wm
self.wm_bit = None
self.wm_size = 0
def read_img(self, filename=None, img=None):
if img is None:
# 从文件读入图片
img = cv2.imread(filename, flags=cv2.IMREAD_UNCHANGED)
assert img is not None, "image file '{filename}' not read".format(filename=filename)
self.bwm_core.read_img_arr(img=img)
return img
def read_wm(self, wm_content, mode='img'):
assert mode in ('img', 'str', 'bit'), "mode in ('img','str','bit')"
if mode == 'img':
wm = cv2.imread(filename=wm_content, flags=cv2.IMREAD_GRAYSCALE)
assert wm is not None, 'file "{filename}" not read'.format(filename=wm_content)
# 读入图片格式的水印,并转为一维 bit 格式,抛弃灰度级别
self.wm_bit = wm.flatten() > 128
elif mode == 'str':
byte = bin(int(wm_content.encode('utf-8').hex(), base=16))[2:]
self.wm_bit = (np.array(list(byte)) == '1')
else:
self.wm_bit = np.array(wm_content)
self.wm_size = self.wm_bit.size
# 水印加密:
np.random.RandomState(self.password_wm).shuffle(self.wm_bit)
self.bwm_core.read_wm(self.wm_bit)
def embed(self, filename=None, compression_ratio=None):
'''
:param filename: string
Save the image file as filename
:param compression_ratio: int or None
If compression_ratio = None, do not compression,
If compression_ratio is integer between 0 and 100, the smaller, the output file is smaller.
:return:
'''
embed_img = self.bwm_core.embed()
if filename is not None:
if compression_ratio is None:
cv2.imwrite(filename=filename, img=embed_img)
elif filename.endswith('.jpg'):
cv2.imwrite(filename=filename, img=embed_img, params=[cv2.IMWRITE_JPEG_QUALITY, compression_ratio])
elif filename.endswith('.png'):
cv2.imwrite(filename=filename, img=embed_img, params=[cv2.IMWRITE_PNG_COMPRESSION, compression_ratio])
else:
cv2.imwrite(filename=filename, img=embed_img)
return embed_img
def extract_decrypt(self, wm_avg):
wm_index = np.arange(self.wm_size)
np.random.RandomState(self.password_wm).shuffle(wm_index)
wm_avg[wm_index] = wm_avg.copy()
return wm_avg
def extract(self, filename=None, embed_img=None, wm_shape=None, out_wm_name=None, mode='img'):
assert wm_shape is not None, 'wm_shape needed'
if filename is not None:
embed_img = cv2.imread(filename, flags=cv2.IMREAD_COLOR)
assert embed_img is not None, "{filename} not read".format(filename=filename)
self.wm_size = np.array(wm_shape).prod()
if mode in ('str', 'bit'):
wm_avg = self.bwm_core.extract_with_kmeans(img=embed_img, wm_shape=wm_shape)
else:
wm_avg = self.bwm_core.extract(img=embed_img, wm_shape=wm_shape)
# 解密:
wm = self.extract_decrypt(wm_avg=wm_avg)
# 转化为指定格式:
if mode == 'img':
wm = 255 * wm.reshape(wm_shape[0], wm_shape[1])
cv2.imwrite(out_wm_name, wm)
elif mode == 'str':
byte = ''.join(str((i >= 0.5) * 1) for i in wm)
wm = bytes.fromhex(hex(int(byte, base=2))[2:]).decode('utf-8', errors='replace')
return wm
================================================
FILE: blind_watermark/bwm_core.py
================================================
#!/usr/bin/env python3
# coding=utf-8
# @Time : 2021/12/17
# @Author : github.com/guofei9987
import numpy as np
from numpy.linalg import svd
import copy
import cv2
from cv2 import dct, idct
from pywt import dwt2, idwt2
from .pool import AutoPool
class WaterMarkCore:
def __init__(self, password_img=1, mode='common', processes=None):
self.block_shape = np.array([4, 4])
self.password_img = password_img
self.d1, self.d2 = 36, 20 # d1/d2 越大鲁棒性越强,但输出图片的失真越大
# init data
self.img, self.img_YUV = None, None # self.img 是原图,self.img_YUV 对像素做了加白偶数化
self.ca, self.hvd, = [np.array([])] * 3, [np.array([])] * 3 # 每个通道 dct 的结果
self.ca_block = [np.array([])] * 3 # 每个 channel 存一个四维 array,代表四维分块后的结果
self.ca_part = [np.array([])] * 3 # 四维分块后,有时因不整除而少一部分,self.ca_part 是少这一部分的 self.ca
self.wm_size, self.block_num = 0, 0 # 水印的长度,原图片可插入信息的个数
self.pool = AutoPool(mode=mode, processes=processes)
self.fast_mode = False
self.alpha = None # 用于处理透明图
def init_block_index(self):
self.block_num = self.ca_block_shape[0] * self.ca_block_shape[1]
assert self.wm_size < self.block_num, IndexError(
'最多可嵌入{}kb信息,多于水印的{}kb信息,溢出'.format(self.block_num / 1000, self.wm_size / 1000))
# self.part_shape 是取整后的ca二维大小,用于嵌入时忽略右边和下面对不齐的细条部分。
self.part_shape = self.ca_block_shape[:2] * self.block_shape
self.block_index = [(i, j) for i in range(self.ca_block_shape[0]) for j in range(self.ca_block_shape[1])]
def read_img_arr(self, img):
# 处理透明图
self.alpha = None
if img.shape[2] == 4:
if img[:, :, 3].min() < 255:
self.alpha = img[:, :, 3]
img = img[:, :, :3]
# 读入图片->YUV化->加白边使像素变偶数->四维分块
self.img = img.astype(np.float32)
self.img_shape = self.img.shape[:2]
# 如果不是偶数,那么补上白边,Y(明亮度)UV(颜色)
self.img_YUV = cv2.copyMakeBorder(cv2.cvtColor(self.img, cv2.COLOR_BGR2YUV),
0, self.img.shape[0] % 2, 0, self.img.shape[1] % 2,
cv2.BORDER_CONSTANT, value=(0, 0, 0))
self.ca_shape = [(i + 1) // 2 for i in self.img_shape]
self.ca_block_shape = (self.ca_shape[0] // self.block_shape[0], self.ca_shape[1] // self.block_shape[1],
self.block_shape[0], self.block_shape[1])
strides = 4 * np.array([self.ca_shape[1] * self.block_shape[0], self.block_shape[1], self.ca_shape[1], 1])
for channel in range(3):
self.ca[channel], self.hvd[channel] = dwt2(self.img_YUV[:, :, channel], 'haar')
# 转为4维度
self.ca_block[channel] = np.lib.stride_tricks.as_strided(self.ca[channel].astype(np.float32),
self.ca_block_shape, strides)
def read_wm(self, wm_bit):
self.wm_bit = wm_bit
self.wm_size = wm_bit.size
def block_add_wm(self, arg):
if self.fast_mode:
return self.block_add_wm_fast(arg)
else:
return self.block_add_wm_slow(arg)
def block_add_wm_slow(self, arg):
block, shuffler, i = arg
# dct->(flatten->加密->逆flatten)->svd->打水印->逆svd->(flatten->解密->逆flatten)->逆dct
wm_1 = self.wm_bit[i % self.wm_size]
block_dct = dct(block)
# 加密(打乱顺序)
block_dct_shuffled = block_dct.flatten()[shuffler].reshape(self.block_shape)
u, s, v = svd(block_dct_shuffled)
s[0] = (s[0] // self.d1 + 1 / 4 + 1 / 2 * wm_1) * self.d1
if self.d2:
s[1] = (s[1] // self.d2 + 1 / 4 + 1 / 2 * wm_1) * self.d2
block_dct_flatten = np.dot(u, np.dot(np.diag(s), v)).flatten()
block_dct_flatten[shuffler] = block_dct_flatten.copy()
return idct(block_dct_flatten.reshape(self.block_shape))
def block_add_wm_fast(self, arg):
# dct->svd->打水印->逆svd->逆dct
block, shuffler, i = arg
wm_1 = self.wm_bit[i % self.wm_size]
u, s, v = svd(dct(block))
s[0] = (s[0] // self.d1 + 1 / 4 + 1 / 2 * wm_1) * self.d1
return idct(np.dot(u, np.dot(np.diag(s), v)))
def embed(self):
self.init_block_index()
embed_ca = copy.deepcopy(self.ca)
embed_YUV = [np.array([])] * 3
self.idx_shuffle = random_strategy1(self.password_img, self.block_num,
self.block_shape[0] * self.block_shape[1])
for channel in range(3):
tmp = self.pool.map(self.block_add_wm,
[(self.ca_block[channel][self.block_index[i]], self.idx_shuffle[i], i)
for i in range(self.block_num)])
for i in range(self.block_num):
self.ca_block[channel][self.block_index[i]] = tmp[i]
# 4维分块变回2维
self.ca_part[channel] = np.concatenate(np.concatenate(self.ca_block[channel], 1), 1)
# 4维分块时右边和下边不能整除的长条保留,其余是主体部分,换成 embed 之后的频域的数据
embed_ca[channel][:self.part_shape[0], :self.part_shape[1]] = self.ca_part[channel]
# 逆变换回去
embed_YUV[channel] = idwt2((embed_ca[channel], self.hvd[channel]), "haar")
# 合并3通道
embed_img_YUV = np.stack(embed_YUV, axis=2)
# 之前如果不是2的整数,增加了白边,这里去除掉
embed_img_YUV = embed_img_YUV[:self.img_shape[0], :self.img_shape[1]]
embed_img = cv2.cvtColor(embed_img_YUV, cv2.COLOR_YUV2BGR)
embed_img = np.clip(embed_img, a_min=0, a_max=255)
if self.alpha is not None:
embed_img = cv2.merge([embed_img.astype(np.uint8), self.alpha])
return embed_img
def block_get_wm(self, args):
if self.fast_mode:
return self.block_get_wm_fast(args)
else:
return self.block_get_wm_slow(args)
def block_get_wm_slow(self, args):
block, shuffler = args
# dct->flatten->加密->逆flatten->svd->解水印
block_dct_shuffled = dct(block).flatten()[shuffler].reshape(self.block_shape)
u, s, v = svd(block_dct_shuffled)
wm = (s[0] % self.d1 > self.d1 / 2) * 1
if self.d2:
tmp = (s[1] % self.d2 > self.d2 / 2) * 1
wm = (wm * 3 + tmp * 1) / 4
return wm
def block_get_wm_fast(self, args):
block, shuffler = args
# dct->svd->解水印
u, s, v = svd(dct(block))
wm = (s[0] % self.d1 > self.d1 / 2) * 1
return wm
def extract_raw(self, img):
# 每个分块提取 1 bit 信息
self.read_img_arr(img=img)
self.init_block_index()
wm_block_bit = np.zeros(shape=(3, self.block_num)) # 3个channel,length 个分块提取的水印,全都记录下来
self.idx_shuffle = random_strategy1(seed=self.password_img,
size=self.block_num,
block_shape=self.block_shape[0] * self.block_shape[1], # 16
)
for channel in range(3):
wm_block_bit[channel, :] = self.pool.map(self.block_get_wm,
[(self.ca_block[channel][self.block_index[i]], self.idx_shuffle[i])
for i in range(self.block_num)])
return wm_block_bit
def extract_avg(self, wm_block_bit):
# 对循环嵌入+3个 channel 求平均
wm_avg = np.zeros(shape=self.wm_size)
for i in range(self.wm_size):
wm_avg[i] = wm_block_bit[:, i::self.wm_size].mean()
return wm_avg
def extract(self, img, wm_shape):
self.wm_size = np.array(wm_shape).prod()
# 提取每个分块埋入的 bit:
wm_block_bit = self.extract_raw(img=img)
# 做平均:
wm_avg = self.extract_avg(wm_block_bit)
return wm_avg
def extract_with_kmeans(self, img, wm_shape):
wm_avg = self.extract(img=img, wm_shape=wm_shape)
return one_dim_kmeans(wm_avg)
def one_dim_kmeans(inputs):
threshold = 0
e_tol = 10 ** (-6)
center = [inputs.min(), inputs.max()] # 1. 初始化中心点
for i in range(300):
threshold = (center[0] + center[1]) / 2
is_class01 = inputs > threshold # 2. 检查所有点与这k个点之间的距离,每个点归类到最近的中心
center = [inputs[~is_class01].mean(), inputs[is_class01].mean()] # 3. 重新找中心点
if np.abs((center[0] + center[1]) / 2 - threshold) < e_tol: # 4. 停止条件
threshold = (center[0] + center[1]) / 2
break
is_class01 = inputs > threshold
return is_class01
def random_strategy1(seed, size, block_shape):
return np.random.RandomState(seed) \
.random(size=(size, block_shape)) \
.argsort(axis=1)
def random_strategy2(seed, size, block_shape):
one_line = np.random.RandomState(seed) \
.random(size=(1, block_shape)) \
.argsort(axis=1)
return np.repeat(one_line, repeats=size, axis=0)
================================================
FILE: blind_watermark/cli_tools.py
================================================
from optparse import OptionParser
from .blind_watermark import WaterMark
usage1 = 'blind_watermark --embed --pwd 1234 image.jpg "watermark text" embed.png'
usage2 = 'blind_watermark --extract --pwd 1234 --wm_shape 111 embed.png'
optParser = OptionParser(usage=usage1 + '\n' + usage2)
optParser.add_option('--embed', dest='work_mode', action='store_const', const='embed'
, help='Embed watermark into images')
optParser.add_option('--extract', dest='work_mode', action='store_const', const='extract'
, help='Extract watermark from images')
optParser.add_option('-p', '--pwd', dest='password', help='password, like 1234')
optParser.add_option('--wm_shape', dest='wm_shape', help='Watermark shape, like 120')
(opts, args) = optParser.parse_args()
def main():
bwm1 = WaterMark(password_img=int(opts.password))
if opts.work_mode == 'embed':
if not len(args) == 3:
print('Error! Usage: ')
print(usage1)
return
else:
bwm1.read_img(args[0])
bwm1.read_wm(args[1], mode='str')
bwm1.embed(args[2])
print('Embed succeed! to file ', args[2])
print('Put down watermark size:', len(bwm1.wm_bit))
if opts.work_mode == 'extract':
if not len(args) == 1:
print('Error! Usage: ')
print(usage2)
return
else:
wm_str = bwm1.extract(filename=args[0], wm_shape=int(opts.wm_shape), mode='str')
print('Extract succeed! watermark is:')
print(wm_str)
'''
python -m blind_watermark.cli_tools --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
python -m blind_watermark.cli_tools --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
cd examples
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
'''
================================================
FILE: blind_watermark/pool.py
================================================
import sys
import multiprocessing
import warnings
if sys.platform != 'win32':
multiprocessing.set_start_method('fork')
class CommonPool(object):
def map(self, func, args):
return list(map(func, args))
class AutoPool(object):
def __init__(self, mode, processes):
if mode == 'multiprocessing' and sys.platform == 'win32':
warnings.warn('multiprocessing not support in windows, turning to multithreading')
mode = 'multithreading'
self.mode = mode
self.processes = processes
if mode == 'vectorization':
pass
elif mode == 'cached':
pass
elif mode == 'multithreading':
from multiprocessing.dummy import Pool as ThreadPool
self.pool = ThreadPool(processes=processes)
elif mode == 'multiprocessing':
from multiprocessing import Pool
self.pool = Pool(processes=processes)
else: # common
self.pool = CommonPool()
def map(self, func, args):
return self.pool.map(func, args)
================================================
FILE: blind_watermark/recover.py
================================================
import cv2
import numpy as np
import functools
# 一个帮助缓存化加速的类,引入事实上的全局变量
class MyValues:
def __init__(self):
self.idx = 0
self.image, self.template = None, None
def set_val(self, image, template):
self.idx += 1
self.image, self.template = image, template
my_value = MyValues()
@functools.lru_cache(maxsize=None, typed=False)
def match_template(w, h, idx):
image, template = my_value.image, my_value.template
resized = cv2.resize(template, dsize=(w, h))
scores = cv2.matchTemplate(image, resized, cv2.TM_CCOEFF_NORMED)
ind = np.unravel_index(np.argmax(scores, axis=None), scores.shape)
return ind, scores[ind]
def match_template_by_scale(scale):
image, template = my_value.image, my_value.template
w, h = round(template.shape[1] * scale), round(template.shape[0] * scale)
ind, score = match_template(w, h, idx=my_value.idx)
return ind, score, scale
def search_template(scale=(0.5, 2), search_num=200):
image, template = my_value.image, my_value.template
# 局部暴力搜索算法,寻找最优的scale
tmp = []
min_scale, max_scale = scale
max_scale = min(max_scale, image.shape[0] / template.shape[0], image.shape[1] / template.shape[1])
max_idx = 0
for i in range(2):
for scale in np.linspace(min_scale, max_scale, search_num):
ind, score, scale = match_template_by_scale(scale)
tmp.append([ind, score, scale])
# 寻找最佳
max_idx = 0
max_score = 0
for idx, (ind, score, scale) in enumerate(tmp):
if score > max_score:
max_idx, max_score = idx, score
min_scale, max_scale = tmp[max(0, max_idx - 1)][2], tmp[min(len(tmp) - 1, max_idx + 1)][2]
search_num = 2 * int((max_scale - min_scale) * max(template.shape[1], template.shape[0])) + 1
return tmp[max_idx]
def estimate_crop_parameters(original_file=None, template_file=None, ori_img=None, tem_img=None
, scale=(0.5, 2), search_num=200):
# 推测攻击后的图片,在原图片中的位置、大小
if template_file:
tem_img = cv2.imread(template_file, cv2.IMREAD_GRAYSCALE) # template image
if original_file:
ori_img = cv2.imread(original_file, cv2.IMREAD_GRAYSCALE) # image
if scale[0] == scale[1] == 1:
# 不缩放
scale_infer = 1
scores = cv2.matchTemplate(ori_img, tem_img, cv2.TM_CCOEFF_NORMED)
ind = np.unravel_index(np.argmax(scores, axis=None), scores.shape)
ind, score = ind, scores[ind]
else:
my_value.set_val(image=ori_img, template=tem_img)
ind, score, scale_infer = search_template(scale=scale, search_num=search_num)
w, h = int(tem_img.shape[1] * scale_infer), int(tem_img.shape[0] * scale_infer)
x1, y1, x2, y2 = ind[1], ind[0], ind[1] + w, ind[0] + h
return (x1, y1, x2, y2), ori_img.shape, score, scale_infer
def recover_crop(template_file=None, tem_img=None, output_file_name=None, loc=None, image_o_shape=None):
if template_file:
tem_img = cv2.imread(template_file) # template image
(x1, y1, x2, y2) = loc
img_recovered = np.zeros((image_o_shape[0], image_o_shape[1], 3))
img_recovered[y1:y2, x1:x2, :] = cv2.resize(tem_img, dsize=(x2 - x1, y2 - y1))
if output_file_name:
cv2.imwrite(output_file_name, img_recovered)
return img_recovered
================================================
FILE: blind_watermark/requirements.txt
================================================
blind-watermark
================================================
FILE: blind_watermark/version.py
================================================
__version__ = '0.4.4'
class Notes:
def __init__(self):
self.show = True
def print_notes(self):
if self.show:
print(f'''
Welcome to use blind-watermark, version = {__version__}
Make sure the version is the same when encode and decode
Your star means a lot: https://github.com/guofei9987/blind_watermark
This message only show once. To close it: `blind_watermark.bw_notes.close()`
''')
self.close()
def close(self):
self.show = False
bw_notes = Notes()
================================================
FILE: docs/.nojekyll
================================================
================================================
FILE: docs/README.md
================================================
# [blind_watermark](https://github.com/guofei9987/blind_watermark)
[](https://pypi.org/project/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://pypi.org/project/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/stargazers)
[](https://github.com/guofei9987/blind_watermark/network/members)
[](https://gitter.im/guofei9987/blind_watermark?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Heuristic Algorithms in Python
(Genetic Algorithm, Particle Swarm Optimization, Simulated Annealing, Ant Colony Algorithm, Immune Algorithm,Artificial Fish Swarm Algorithm in Python)
- **Documentation:** [https://blind_watermark.github.io/blind_watermark/#/en/](https://blind_watermark.github.io/blind_watermark/#/en/)
- **文档:** [https://blind_watermark.github.io/blind_watermark/#/zh/](https://blind_watermark.github.io/blind_watermark/#/zh/)
- **Source code:** [https://github.com/guofei9987/blind_watermark](https://github.com/guofei9987/blind_watermark)
================================================
FILE: docs/_coverpage.md
================================================
<!--  -->
# blind_watermark
> 数字盲水印
* 图片水印
* 比特水印
[GitHub](https://github.com/guofei9987/blind_watermark/)
[Get Started](/en/README)
================================================
FILE: docs/_navbar.md
================================================
- Translations
- [:uk: English](/en/)
- [:cn: 中文](/zh/)
================================================
FILE: docs/_sidebar.md
================================================
* [English Document](docs/en.md)
* [中文文档](docs/zh.md)
================================================
FILE: docs/en/README.md
================================================
# blind-watermark
Blind watermark based on dct and svd.
[](https://pypi.org/project/blind_watermark/)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://github.com/guofei9987/blind_watermark/blob/master/LICENSE)


[](https://github.com/guofei9987/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/fork)
[](https://pepy.tech/project/blind-watermark)
[](https://github.com/guofei9987/blind_watermark/discussions)
- **Documentation:** [https://BlindWatermark.github.io/blind_watermark/#/en/](https://BlindWatermark.github.io/blind_watermark/#/en/)
- **文档:** [https://BlindWatermark.github.io/blind_watermark/#/zh/](https://BlindWatermark.github.io/blind_watermark/#/zh/)
- **中文 readme** [README_cn.md](README_cn.md)
- **Source code:** [https://github.com/guofei9987/blind_watermark](https://github.com/guofei9987/blind_watermark)
# install
```bash
pip install blind-watermark
```
For the current developer version:
```bach
git clone git@github.com:guofei9987/blind_watermark.git
cd blind_watermark
pip install .
```
# How to use
### Use in bash
```bash
# embed watermark into image:
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
# extract watermark from image:
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
```
## Use in Python
Original Image + Watermark = Watermarked Image
 + '@guofei9987 开源万岁!' = 
See the [codes](/examples/example_str.py)
Embed watermark:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_img('pic/ori_img.jpg')
wm = '@guofei9987 开源万岁!'
bwm1.read_wm(wm, mode='str')
bwm1.embed('output/embedded.png')
len_wm = len(bwm1.wm_bit)
print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))
```
Extract watermark:
```python
bwm1 = WaterMark(password_img=1, password_wm=1)
wm_extract = bwm1.extract('output/embedded.png', wm_shape=len_wm, mode='str')
print(wm_extract)
```
Output:
>@guofei9987 开源万岁!
### attacks on Watermarked Image
|attack method|image after attack|extracted watermark|
|--|--|--|
|Rotate 45 Degrees||'@guofei9987 开源万岁!'|
|Random crop||'@guofei9987 开源万岁!'|
|Masks|  |'@guofei9987 开源万岁!'|
|50% Horizontal cut||'@guofei9987 开源万岁!'|
|50% Vertical cut||'@guofei9987 开源万岁!'|
|Resize 0.5||'@guofei9987 开源万岁!'|
|Pepper Noise||'@guofei9987 开源万岁!'|
|Brightness 10% Down||'@guofei9987 开源万岁!'|
### embed images
embed watermark:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_wm=1, password_img=1)
# read original image
bwm1.read_img('pic/ori_img.jpg')
# read watermark
bwm1.read_wm('pic/watermark.png')
# embed
bwm1.embed('output/embedded.png')
```
Extract watermark:
```python
bwm1 = WaterMark(password_wm=1, password_img=1)
# notice that wm_shape is necessary
bwm1.extract(filename='output/embedded.png', wm_shape=(128, 128), out_wm_name='output/extracted.png', )
```
|attack method|image after attack|extracted watermark|
|--|--|--|
|Rotate 45 Degrees|||
|Random crop|||
|Mask|  ||
### embed array of bits
See it [here](/examples/example_bit.py)
As demo, we embed 6 bytes data:
```python
wm = [True, False, True, True, True, False]
```
Embed:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_ori_img('pic/ori_img.jpg')
bwm1.read_wm([True, False, True, True, True, False], mode='bit')
bwm1.embed('output/embedded.png')
```
Extract:
```python
bwm1 = WaterMark(password_img=1, password_wm=1, wm_shape=6)
wm_extract = bwm1.extract('output/打上水印的图.png', mode='bit')
print(wm_extract)
```
Notice that `wm_shape` (shape of watermark) is necessary
The output `wm_extract` is an array of float. set a threshold such as 0.5.
# Concurrency
```python
WaterMark(..., processes=None)
```
- `processes`: number of processes, can be integer. Default `None`, meaning use all processes.
## Related Project
text_blind_watermark: [https://github.com/guofei9987/text_blind_watermark](https://github.com/guofei9987/text_blind_watermark)
Embed message into text.
================================================
FILE: docs/en/_coverpage.md
================================================
# blind_watermark
> Blind Watermark
* [](https://pypi.org/project/blind_watermark/)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://github.com/guofei9987/blind_watermark/blob/master/LICENSE)


[](https://github.com/guofei9987/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/fork)
[](https://pepy.tech/project/blind-watermark)
[](https://github.com/guofei9987/blind_watermark/discussions)
* embed a picture
* embed a string
* embed byte-file
[GitHub](https://github.com/guofei9987/blind_watermark/)
[Get Started](/en/README)
================================================
FILE: docs/en/_sidebar.md
================================================
* [Document](en/README.md)
================================================
FILE: docs/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>blind_watermark</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="description" content="Description">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: '',
repo: ''
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script>
window.$docsify = {
plugins: [
function (hook, vm) {
hook.beforeEach(function (html) {
var url = 'https://github.com/guofei9987/blind_watermark/blob/master/docs/' + vm.route.file;
var editHtml = '[:memo: Edit](' + url + ')\n';
return editHtml
+ html
+ '\n\n----\n\n'
+ ' '
+ editHtml
})
}
],
auto2top: true,
coverpage: ['/', '/en/', '/zh/'],
executeScript: true,
loadSidebar: true,
loadNavbar: true,
mergeNavbar: true,
maxLevel: 4,
subMaxLevel: 2,
notFoundPage: 'README.md'
};
</script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
<!-- 代码高亮 -->
<script src="//unpkg.com/prismjs/components/prism-python.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
</body>
</html>
================================================
FILE: docs/make_doc.py
================================================
# 不想用 Sphinx,也不像弄一堆静态html文件,所以自己写个咯
'''
需要从readme中解析出:
1. "-> Demo code: [examples/demo_pso.py](examples/demo_pso.py)"
2. 三个```python为开头,三个 ``` 为结尾
3. 从py文件中读出文本,并替换
4. 前几行是求star,只在readme中出现
需要从py文件中解析出:
1. # %% 做断点后赋予index值,然后插入readme
'''
import os
import sys
import re
def search_code(py_file_name, section_idx):
'''
给定py文件名和section序号,返回一个list,内容是py文件中的code(markdown格式)
:param py_file_name:
:param section_idx:
:return:
'''
with open('../' + py_file_name, encoding='utf-8', mode="r") as f:
content = f.readlines()
content_new, i, search_idx, idx_first_match = [], 0, 0, None
while i < len(content) and search_idx <= section_idx:
if content[i].startswith('# %%'):
search_idx += 1
i += 1 # 带井号百分号的那一行也跳过去,不要放到文档里面
if search_idx < section_idx:
pass
elif search_idx == section_idx:
idx_first_match = idx_first_match or i # record first match line
content_new.append(content[i])
i += 1
return [
'-> Demo code: [{py_file_name}#s{section_idx}](https://github.com/guofei9987/blind_watermark/blob/master/{py_file_name}#L{idx_first_match})\n'.
format(py_file_name=py_file_name, section_idx=section_idx + 1, idx_first_match=idx_first_match),
'```python\n'] \
+ content_new \
+ ['```\n']
# %%
def make_doc(origin_file):
with open(origin_file, encoding='utf-8', mode="r") as f_readme:
readme = f_readme.readlines()
regex = re.compile('\[examples/[\w#.]+\]')
readme_idx = 0
readme_new = []
while readme_idx < len(readme):
readme_line = readme[readme_idx]
if readme_line.startswith('-> Demo code: ['):
# 找到中括号里面的内容,解析为文件名,section号
py_file_name, section_idx = regex.findall(readme[readme_idx])[0][1:-1].split('#s')
section_idx = int(section_idx) - 1
print('插入代码: ', py_file_name, section_idx)
content_new = search_code(py_file_name, section_idx)
readme_new.extend(content_new)
# 往下寻找第一个代码结束位置
while readme[readme_idx] != '```\n':
readme_idx += 1
else:
# 如果不需要插入代码,就用原本的内容
readme_new.append(readme_line)
readme_idx += 1
return readme_new
# 主页 README 和 en/README
readme_new = make_doc(origin_file='../README.md')
with open('../README.md', encoding='utf-8', mode="w") as f_readme:
f_readme.writelines(readme_new)
with open('en/README.md', encoding='utf-8', mode="w") as f_readme_en:
f_readme_en.writelines(readme_new[20:])
# 跟目录的 README_cn.md 和 zh/README.md
readme_zh = make_doc(origin_file='../README_cn.md')
with open('../README_cn.md', encoding='utf-8', mode="w") as f_readme:
f_readme.writelines(readme_zh)
with open('zh/README.md', encoding='utf-8', mode="w") as f_readme_en:
f_readme_en.writelines(readme_zh)
# docs = ['zh/README.md','en/README.md'
# ]
# for i in docs:
# docs_new = make_doc(origin_file=i)
# with open(i, encoding='utf-8', mode="w") as f:
# f.writelines(docs_new)
# sys.exit()
================================================
FILE: docs/run_server.bat
================================================
docsify serve
================================================
FILE: docs/vue.css
================================================
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600");
* {
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
box-sizing: border-box
}
body:not(.ready) {
overflow: hidden
}
body:not(.ready) .app-nav, body:not(.ready) > nav, body:not(.ready) [data-cloak] {
display: none
}
div#app {
font-size: 30px;
font-weight: lighter;
margin: 40vh auto;
text-align: center
}
div#app:empty:before {
content: "Loading..."
}
.emoji {
height: 1.2rem;
vertical-align: middle
}
.progress {
background-color: var(--theme-color, #42b983);
height: 2px;
left: 0;
position: fixed;
right: 0;
top: 0;
transition: width .2s, opacity .4s;
width: 0;
z-index: 5
}
.search .search-keyword, .search a:hover {
color: var(--theme-color, #42b983)
}
.search .search-keyword {
font-style: normal;
font-weight: 700
}
body, html {
height: 100%
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: #34495e;
font-family: Source Sans Pro, Helvetica Neue, Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden
}
img {
max-width: 100%
}
a[disabled] {
cursor: not-allowed;
opacity: .6
}
kbd {
border: 1px solid #ccc;
border-radius: 3px;
display: inline-block;
font-size: 12px !important;
line-height: 12px;
margin-bottom: 3px;
padding: 3px 5px;
vertical-align: middle
}
li input[type=checkbox] {
margin: 0 .2em .25em 0;
vertical-align: middle
}
.app-nav {
margin: 25px 60px 0 0;
position: absolute;
right: 0;
text-align: right;
z-index: 2
}
.app-nav.no-badge {
margin-right: 0px
}
.app-nav.no-badge ul{
padding: 0 0 0 0
}
.app-nav p {
margin: 0
}
.app-nav > a {
margin: 0 1rem;
padding: 5px 0
}
.app-nav li, .app-nav ul {
display: inline-block;
list-style: none;
margin: 0
}
.app-nav a {
color: inherit;
font-size: 16px;
text-decoration: none;
transition: color .3s
}
.app-nav a.active, .app-nav a:hover {
color: var(--theme-color, #42b983)
}
.app-nav a.active {
border-bottom: 2px solid var(--theme-color, #42b983)
}
.app-nav li {
display: inline-block;
margin: 0 1rem;
padding: 5px 0;
position: relative
}
.app-nav li ul {
background-color: #fff;
border: 1px solid #ddd;
border-bottom-color: #ccc;
border-radius: 4px;
box-sizing: border-box;
display: none;
max-height: calc(100vh - 61px);
overflow-y: auto;
padding: 10px 0;
position: absolute;
right: -15px;
text-align: left;
top: 100%;
white-space: nowrap
}
.app-nav li ul li {
display: block;
font-size: 14px;
line-height: 1rem;
margin: 0;
margin: 8px 14px;
white-space: nowrap
}
.app-nav li ul a {
display: block;
font-size: inherit;
margin: 0;
padding: 0
}
.app-nav li ul a.active {
border-bottom: 0
}
.app-nav li:hover ul {
display: block
}
.github-corner {
border-bottom: 0;
position: fixed;
right: 0;
text-decoration: none;
top: 0;
z-index: 1
}
.github-corner:hover .octo-arm {
animation: a .56s ease-in-out
}
.github-corner svg {
color: #fff;
fill: var(--theme-color, #42b983);
height: 80px;
width: 80px
}
main {
display: block;
position: relative;
width: 100vw;
height: 100%;
z-index: 0
}
main.hidden {
display: none
}
.anchor {
display: inline-block;
text-decoration: none;
transition: all .3s
}
.anchor span {
color: #34495e
}
.anchor:hover {
text-decoration: underline
}
.sidebar {
border-right: 1px solid rgba(0, 0, 0, .07);
overflow-y: auto;
padding: 40px 0 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
transition: transform .25s ease-out;
width: 300px;
z-index: 3
}
.sidebar > h1 {
margin: 0 auto 1rem;
font-size: 1.5rem;
font-weight: 300;
text-align: center
}
.sidebar > h1 a {
color: inherit;
text-decoration: none
}
.sidebar > h1 .app-nav {
display: block;
position: static
}
.sidebar .sidebar-nav {
line-height: 1em;
padding-bottom: 40px
}
.sidebar li.collapse .app-sub-sidebar {
display: none
}
.sidebar ul {
margin: 0 0 0 15px;
padding: 0
}
.sidebar li > p {
font-weight: 700;
margin: 0
}
.sidebar ul, .sidebar ul li {
list-style: none
}
.sidebar ul li a {
border-bottom: none;
display: block
}
.sidebar ul li ul {
padding-left: 20px
}
.sidebar::-webkit-scrollbar {
width: 4px
}
.sidebar::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 4px
}
.sidebar:hover::-webkit-scrollbar-thumb {
background: hsla(0, 0%, 53%, .4)
}
.sidebar:hover::-webkit-scrollbar-track {
background: hsla(0, 0%, 53%, .1)
}
.sidebar-toggle {
background-color: transparent;
background-color: hsla(0, 0%, 100%, .8);
border: 0;
outline: none;
padding: 10px;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
transition: opacity .3s;
width: 284px;
z-index: 4
}
.sidebar-toggle .sidebar-toggle-button:hover {
opacity: .4
}
.sidebar-toggle span {
background-color: var(--theme-color, #42b983);
display: block;
margin-bottom: 4px;
width: 16px;
height: 2px
}
body.sticky .sidebar, body.sticky .sidebar-toggle {
position: fixed
}
.content {
padding-top: 60px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 300px;
transition: left .25s ease
}
.markdown-section {
/*margin: 0 auto;*/
margin: 1em auto;
max-width: 1300px;
padding: 30px 0 40px 0;
position: relative
}
.markdown-section > * {
box-sizing: border-box;
font-size: inherit
}
.markdown-section > :first-child {
margin-top: 0 !important
}
.markdown-section hr {
border: none;
border-bottom: 1px solid #eee;
margin: 2em 0
}
.markdown-section iframe {
border: 1px solid #eee
}
.markdown-section table {
border-collapse: collapse;
border-spacing: 0;
display: block;
margin-bottom: 1rem;
overflow: auto;
width: 100%
}
.markdown-section th {
font-weight: 700
}
.markdown-section td, .markdown-section th {
border: 1px solid #ddd;
padding: 6px 13px
}
.markdown-section tr {
border-top: 1px solid #ccc
}
.markdown-section p.tip, .markdown-section tr:nth-child(2n) {
background-color: #f8f8f8
}
.markdown-section p.tip {
border-bottom-right-radius: 2px;
border-left: 4px solid #f66;
border-top-right-radius: 2px;
margin: 2em 0;
padding: 12px 24px 12px 30px;
position: relative
}
.markdown-section p.tip:before {
background-color: #f66;
border-radius: 100%;
color: #fff;
content: "!";
font-family: Dosis, Source Sans Pro, Helvetica Neue, Arial, sans-serif;
font-size: 14px;
font-weight: 700;
left: -12px;
line-height: 20px;
position: absolute;
height: 20px;
width: 20px;
text-align: center;
top: 14px
}
.markdown-section p.tip code {
background-color: #efefef
}
.markdown-section p.tip em {
color: #34495e
}
.markdown-section p.warn {
background: rgba(66, 185, 131, .1);
border-radius: 2px;
padding: 1rem
}
.markdown-section ul.task-list > li {
list-style-type: none
}
body.close .sidebar {
transform: translateX(-300px)
}
body.close .sidebar-toggle {
width: auto
}
body.close .content {
left: 0
}
@media print {
.app-nav, .github-corner, .sidebar, .sidebar-toggle {
display: none
}
}
@media screen and (max-width: 768px) {
.github-corner, .sidebar, .sidebar-toggle {
position: fixed
}
.app-nav {
margin-top: 16px
}
.app-nav li ul {
top: 30px
}
main {
height: auto;
overflow-x: hidden
}
.sidebar {
left: -300px;
transition: transform .25s ease-out
}
.content {
left: 0;
max-width: 100vw;
position: static;
padding-top: 20px;
transition: transform .25s ease
}
.app-nav, .github-corner {
transition: transform .25s ease-out
}
.sidebar-toggle {
background-color: transparent;
width: auto;
padding: 30px 30px 10px 10px
}
body.close .sidebar {
transform: translateX(300px)
}
body.close .sidebar-toggle {
background-color: hsla(0, 0%, 100%, .8);
transition: background-color 1s;
width: 284px;
padding: 10px
}
body.close .content {
transform: translateX(300px)
}
body.close .app-nav, body.close .github-corner {
display: none
}
.github-corner:hover .octo-arm {
animation: none
}
.github-corner .octo-arm {
animation: a .56s ease-in-out
}
}
@keyframes a {
0%, to {
transform: rotate(0)
}
20%, 60% {
transform: rotate(-25deg)
}
40%, 80% {
transform: rotate(10deg)
}
}
section.cover {
-ms-flex-align: center;
align-items: center;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
display: none
}
section.cover.show {
display: -ms-flexbox;
display: flex
}
section.cover.has-mask .mask {
background-color: #fff;
opacity: .8;
position: absolute;
top: 0;
height: 100%;
width: 100%
}
section.cover .cover-main {
-ms-flex: 1;
flex: 1;
margin: -20px 16px 0;
text-align: center;
z-index: 1
}
section.cover a {
color: inherit
}
section.cover a, section.cover a:hover {
text-decoration: none
}
section.cover p {
line-height: 1.5rem;
margin: 1em 0
}
section.cover h1 {
color: inherit;
font-size: 2.5rem;
font-weight: 300;
margin: .625rem 0 2.5rem;
position: relative;
text-align: center
}
section.cover h1 a {
display: block
}
section.cover h1 small {
bottom: -.4375rem;
font-size: 1rem;
position: absolute
}
section.cover blockquote {
font-size: 1.5rem;
text-align: center
}
section.cover ul {
line-height: 1.8;
list-style-type: none;
margin: 1em auto;
max-width: 500px;
padding: 0
}
section.cover .cover-main > p:last-child a {
border: 1px solid var(--theme-color, #42b983);
border-radius: 2rem;
box-sizing: border-box;
color: var(--theme-color, #42b983);
display: inline-block;
font-size: 1.05rem;
letter-spacing: .1rem;
margin: .5rem 1rem;
padding: .75em 2rem;
text-decoration: none;
transition: all .15s ease
}
section.cover .cover-main > p:last-child a:last-child {
background-color: var(--theme-color, #42b983);
color: #fff
}
section.cover .cover-main > p:last-child a:last-child:hover {
color: inherit;
opacity: .8
}
section.cover .cover-main > p:last-child a:hover {
color: inherit
}
section.cover blockquote > p > a {
border-bottom: 2px solid var(--theme-color, #42b983);
transition: color .3s
}
section.cover blockquote > p > a:hover {
color: var(--theme-color, #42b983)
}
.sidebar, body {
background-color: #fff
}
.sidebar {
color: #364149
}
.sidebar li {
margin: 6px 0
}
.sidebar ul li a {
color: #505d6b;
font-size: 14px;
font-weight: 400;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap
}
.sidebar ul li a:hover {
text-decoration: underline
}
.sidebar ul li ul {
padding: 0
}
.sidebar ul li.active > a {
border-right: 2px solid;
color: var(--theme-color, #42b983);
font-weight: 600
}
.app-sub-sidebar li:before {
content: "";
padding-right: 4px;
float: left
}
.markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4 {
color: #2c3e50;
font-weight: 600
}
.markdown-section strong {
color: red;
font-weight: 600
}
.markdown-section a {
color: var(--theme-color, #42b983);
font-weight: 600
}
.markdown-section h1 {
font-size: 2.25rem;
margin: 0 0 1rem
}
.markdown-section h2 {
background: #c0cda5;
font-size: 2.25rem;
margin: 45px 0 .8rem
}
.markdown-section h3,h4,h5 {
background: #e5f7f3;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 40px 0 .6rem
}
.markdown-section h4 {
font-size: 1rem
}
.markdown-section h5 {
font-size: 0.875rem
}
.markdown-section h6 {
color: #777;
font-size: 0.75rem
}
.markdown-section figure, .markdown-section p {
margin: 1.5em 0 0 0
/*上右下左*/
}
.markdown-section ol, .markdown-section p, .markdown-section ul {
line-height: 1.6rem;
word-spacing: .05rem
}
.markdown-section ol, .markdown-section ul {
margin-top: 0px;
padding-left: 1.5rem
}
.markdown-section blockquote {
border-left: 8px solid var(--theme-color, #42b983);
color: #858585;
margin: 0 0;
padding-left: 20px
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
margin-top: 0
}
.markdown-section iframe {
margin: 1em 0
}
.markdown-section em {
color: #7f8c8d
}
.markdown-section code {
border-radius: 2px;
color: #e96900;
font-size: .8rem;
margin: 0 2px;
padding: 3px 5px;
white-space: pre-wrap
}
.markdown-section code, .markdown-section pre {
background-color: #f8f8f8;
font-family: Roboto Mono, Monaco, courier, monospace
}
.markdown-section pre {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
line-height: 1.5rem;
margin: 1.2em 0;
overflow: auto;
padding: 0 1.4rem;
position: relative;
word-wrap: normal
}
.token.cdata, .token.comment, .token.doctype, .token.prolog {
color: #8e908c
}
.token.namespace {
opacity: .7
}
.token.boolean, .token.number {
color: #c76b29
}
.token.punctuation {
color: #525252
}
.token.property {
color: #c08b30
}
.token.tag {
color: #2973b7
}
.token.string {
color: var(--theme-color, #42b983)
}
.token.selector {
color: #6679cc
}
.token.attr-name {
color: #2973b7
}
.language-css .token.string, .style .token.string, .token.entity, .token.url {
color: #22a2c9
}
.token.attr-value, .token.control, .token.directive, .token.unit {
color: var(--theme-color, #42b983)
}
.token.function, .token.keyword {
color: #e96900
}
.token.atrule, .token.regex, .token.statement {
color: #22a2c9
}
.token.placeholder, .token.variable {
color: #3d8fd1
}
.token.deleted {
text-decoration: line-through
}
.token.inserted {
border-bottom: 1px dotted #202746;
text-decoration: none
}
.token.italic {
font-style: italic
}
.token.bold, .token.important {
font-weight: 700
}
.token.important {
color: #c94922
}
.token.entity {
cursor: help
}
.markdown-section pre > code {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
border-radius: 2px;
color: #525252;
display: block;
font-family: Roboto Mono, Monaco, courier, monospace;
font-size: .8rem;
line-height: inherit;
margin: 0 2px;
max-width: inherit;
overflow: inherit;
padding: 2.2em 5px;
white-space: inherit
}
.markdown-section code:after, .markdown-section code:before {
letter-spacing: .05rem
}
code .token {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
min-height: 1.5rem
}
pre:after {
color: #ccc;
content: attr(data-lang);
font-size: .6rem;
font-weight: 600;
height: 15px;
line-height: 15px;
padding: 5px 10px 0;
position: absolute;
right: 0;
text-align: right;
top: 0
}
================================================
FILE: docs/zh/README.md
================================================
# blind-watermark
基于频域的数字盲水印
[](https://pypi.org/project/blind_watermark/)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://github.com/guofei9987/blind_watermark/blob/master/LICENSE)


[](https://github.com/guofei9987/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/fork)
[](https://pepy.tech/project/blind-watermark)
[](https://github.com/guofei9987/blind_watermark/discussions)
- **Documentation:** [https://BlindWatermark.github.io/blind_watermark/#/en/](https://BlindWatermark.github.io/blind_watermark/#/en/)
- **文档:** [https://BlindWatermark.github.io/blind_watermark/#/zh/](https://BlindWatermark.github.io/blind_watermark/#/zh/)
- **English readme** [README.md](README.md)
- **Source code:** [https://github.com/guofei9987/blind_watermark](https://github.com/guofei9987/blind_watermark)
# 安装
```bash
pip install blind-watermark
```
或者安装最新开发版本
```bach
git clone git@github.com:guofei9987/blind_watermark.git
cd blind_watermark
pip install .
```
# 如何使用
### 命令行中使用
```bash
# 嵌入水印:
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
# 提取水印:
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
```
## Python 中使用
原图 + 水印 = 打上水印的图
 + '@guofei9987 开源万岁!' = 
参考 [代码](/examples/example_str.py)
嵌入水印
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_img('pic/ori_img.jpg')
wm = '@guofei9987 开源万岁!'
bwm1.read_wm(wm, mode='str')
bwm1.embed('output/embedded.png')
len_wm = len(bwm1.wm_bit)
print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))
```
提取水印
```python
bwm1 = WaterMark(password_img=1, password_wm=1)
wm_extract = bwm1.extract('output/embedded.png', wm_shape=len_wm, mode='str')
print(wm_extract)
```
Output:
>@guofei9987 开源万岁!
### 各种攻击后的效果
|攻击方式|攻击后的图片|提取的水印|
|--|--|--|
|旋转攻击45度||'@guofei9987 开源万岁!'|
|随机截图||'@guofei9987 开源万岁!'|
|多遮挡|  |'@guofei9987 开源万岁!'|
|横向裁剪50%||'@guofei9987 开源万岁!'|
|纵向裁剪50%||'@guofei9987 开源万岁!'|
|缩放攻击||'@guofei9987 开源万岁!'|
|椒盐攻击||'@guofei9987 开源万岁!'|
|亮度攻击||'@guofei9987 开源万岁!'|
### 嵌入图片
参考 [代码](/examples/example_str.py)
嵌入:
```python
from blind_watermark import WaterMark
bwm1 = WaterMark(password_wm=1, password_img=1)
# read original image
bwm1.read_img('pic/ori_img.jpg')
# read watermark
bwm1.read_wm('pic/watermark.png')
# embed
bwm1.embed('output/embedded.png')
```
提取:
```python
bwm1 = WaterMark(password_wm=1, password_img=1)
# notice that wm_shape is necessary
bwm1.extract(filename='output/embedded.png', wm_shape=(128, 128), out_wm_name='output/extracted.png', )
```
|攻击方式|攻击后的图片|提取的水印|
|--|--|--|
|旋转攻击45度|||
|随机截图|||
|多遮挡|  ||
### 隐水印还可以是二进制数据
参考 [代码](/examples/example_bit.py)
作为 demo, 如果要嵌入是如下长度为6的二进制数据
```python
wm = [True, False, True, True, True, False]
```
嵌入水印
```python
# 除了嵌入图片,也可以嵌入比特类数据
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_ori_img('pic/ori_img.jpg')
bwm1.read_wm([True, False, True, True, True, False], mode='bit')
bwm1.embed('output/打上水印的图.png')
```
解水印:(注意设定水印形状 `wm_shape`)
```python
bwm1 = WaterMark(password_img=1, password_wm=1, wm_shape=6)
wm_extract = bwm1.extract('output/打上水印的图.png', mode='bit')
print(wm_extract)
```
解出的水印是一个0~1之间的实数,方便用户自行卡阈值。如果水印信息量远小于图片可容纳量,偏差极小。
# 并行计算
```python
WaterMark(..., processes=None)
```
- `processes`: 整数,指定线程数。默认为 `None`, 表示使用全部线程。
## 相关项目
text_blind_watermark: [https://github.com/guofei9987/text_blind_watermark](https://github.com/guofei9987/text_blind_watermark)
文本盲水印,把信息隐秘地打入文本.
================================================
FILE: docs/zh/_coverpage.md
================================================
<!--  -->
# blind_watermark
> 数字盲水印
* [](https://pypi.org/project/blind_watermark/)
[](https://travis-ci.com/guofei9987/blind_watermark)
[](https://codecov.io/gh/guofei9987/blind_watermark)
[](https://github.com/guofei9987/blind_watermark/blob/master/LICENSE)


[](https://github.com/guofei9987/blind_watermark/)
[](https://github.com/guofei9987/blind_watermark/fork)
[](https://pepy.tech/project/blind-watermark)
[](https://github.com/guofei9987/blind_watermark/discussions)
* 嵌入图片
* 嵌入文本
* 嵌入二进制
[GitHub](https://github.com/guofei9987/blind_watermark/)
[开始](/zh/README)
================================================
FILE: docs/zh/_sidebar.md
================================================
* [文档](zh/README.md)
================================================
FILE: examples/example_bit.py
================================================
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from blind_watermark import att
from blind_watermark import WaterMark
import cv2
from blind_watermark.recover import estimate_crop_parameters, recover_crop
import numpy as np
import os
os.chdir(os.path.dirname(__file__))
# %%
bwm = WaterMark(password_img=1, password_wm=1)
# 读取原图
bwm.read_img('pic/ori_img.jpeg')
# 读取水印
wm = [True, False, True, False, True, False, True, False, True, False]
bwm.read_wm(wm, mode='bit')
# 打上盲水印
bwm.embed('output/embedded.png')
len_wm = len(wm) # 解水印需要用到长度
ori_img_shape = cv2.imread('pic/ori_img.jpeg').shape[:2] # 抗攻击需要知道原图的shape
h, w = ori_img_shape
# %% 解水印
# 注意设定水印的长宽wm_shape
bwm1 = WaterMark(password_img=1, password_wm=1)
wm_extract = bwm1.extract('output/embedded.png', wm_shape=len_wm, mode='bit')
print("不攻击的提取结果:", wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
# %%截屏攻击
loc = ((0.3, 0.1), (0.7, 0.9))
att.cut_att(input_filename='output/embedded.png', output_file_name='output/截屏攻击.png', loc=loc)
bwm1 = WaterMark(password_wm=1, password_img=1)
wm_extract = bwm1.extract('output/截屏攻击.png', wm_shape=len_wm, mode='bit')
print("截屏攻击{loc}后的提取结果:".format(loc=loc), wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
# %%截屏攻击1 = 裁剪攻击 + 缩放攻击 + 知道攻击参数(之后按照参数还原)
loc_r = ((0.1, 0.1), (0.5, 0.5))
scale = 0.7
x1, y1, x2, y2 = int(w * loc_r[0][0]), int(h * loc_r[0][1]), int(w * loc_r[1][0]), int(h * loc_r[1][1])
# 截屏攻击
att.cut_att3(input_filename='output/embedded.png', output_file_name='output/截屏攻击1.png',
loc=(x1, y1, x2, y2), scale=scale)
recover_crop(template_file='output/截屏攻击1.png', output_file_name='output/截屏攻击1_还原.png',
loc=(x1, y1, x2, y2), image_o_shape=ori_img_shape)
bwm1 = WaterMark(password_wm=1, password_img=1)
wm_extract = bwm1.extract('output/截屏攻击1_还原.png', wm_shape=len_wm, mode='bit')
print("截屏攻击{loc}后的提取结果:".format(loc=loc), wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
# %%椒盐攻击
ratio = 0.05
att.salt_pepper_att(input_filename='output/embedded.png', output_file_name='output/椒盐攻击.png', ratio=ratio)
# ratio是椒盐概率
# 提取
wm_extract = bwm1.extract('output/椒盐攻击.png', wm_shape=len_wm, mode='bit')
print(f"椒盐攻击ratio={ratio}后的提取结果:", wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
# %%旋转攻击
att.rot_att(input_filename='output/embedded.png', output_file_name='output/旋转攻击.png', angle=45)
att.rot_att(input_filename='output/旋转攻击.png', output_file_name='output/旋转攻击_还原.png', angle=-45)
# 提取水印
bwm1 = WaterMark(password_wm=1, password_img=1)
wm_extract = bwm1.extract('output/旋转攻击_还原.png', wm_shape=len_wm, mode='bit')
print("旋转攻击后的提取结果:", wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
# %%遮挡攻击
n = 60
att.shelter_att(input_filename='output/embedded.png', output_file_name='output/多遮挡攻击.png', ratio=0.1, n=n)
# 提取
bwm1 = WaterMark(password_wm=1, password_img=1)
wm_extract = bwm1.extract('output/多遮挡攻击.png', wm_shape=len_wm, mode='bit')
print(f"遮挡攻击{n}后的提取结果:", wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
# %%缩放攻击
att.resize_att(input_filename='output/embedded.png', output_file_name='output/缩放攻击.png', out_shape=(800, 600))
att.resize_att(input_filename='output/缩放攻击.png', output_file_name='output/缩放攻击_还原.png', out_shape=ori_img_shape[::-1])
# out_shape 是分辨率,需要颠倒一下
bwm1 = WaterMark(password_wm=1, password_img=1)
wm_extract = bwm1.extract('output/缩放攻击_还原.png', wm_shape=len_wm, mode='bit')
print("缩放攻击后的提取结果:", wm_extract)
assert np.all(wm == wm_extract), '提取水印和原水印不一致'
================================================
FILE: examples/example_demo.ipynb
================================================
{
"cells": [
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from blind_watermark import WaterMark\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.pylab as pylab\n",
"from PIL import Image"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Embed Watermark"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Put down the length of wm_bit 135\n"
]
}
],
"source": [
"bwm1 = WaterMark(password_img=1, password_wm=1)\n",
"bwm1.read_img('./pic/Lena_512x512.jpg')\n",
"wm = '@testingwatermark'\n",
"bwm1.read_wm(wm, mode='str')\n",
"bwm1.embed('output/embedded.png')\n",
"len_wm = len(bwm1.wm_bit)\n",
"print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"original_img = Image.open(\"./pic/Lena_512x512.jpg\")\n",
"wat_img = Image.open(\"./output/embedded.png\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABDwAAAHiCAYAAAAEZtwbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOz9e7R1W7YXhP36GGPOtfb+Xqfq1uNQde8FEtGghhiMoEQCrYkICoEgGoIoEBNQkbQkxrQAQngpxkZiMCggNh8tPkAJpBklii3qBfRC0JYA3ohQ996qe6vqvL7nfq415xi954/e+1x9jzP3d04VdW6dc539tO/svdeaa87xXuP3G7/eO4kINttss80222yzzTbbbLPNNttss81+NFn6dhdgs80222yzzTbbbLPNNttss8022+xbbRvhsdlmm2222WabbbbZZpttttlmm/2os43w2GyzzTbbbLPNNttss80222yzzX7U2UZ4bLbZZpttttlmm2222WabbbbZZj/qbCM8Nttss80222yzzTbbbLPNNttssx91thEem2222WabbbbZZpttttlmm2222Y862wiPzTb7ETYi+vVE9C98q6/9EPcSIvorvhX32myzzTbbbLPNNtvs9UZEP872X+VbcK8vE9HP+laUa7PN/utkG+Gx2WZ/GUZEv4KI/jwR3RDR20T0e4jojdd9RkT+CRH5n32Y+38j1/7lGBH9x0T0kT9ns80222yzzTb7r68R0a8joj/avfaX7nntl3zAvX4mEX31oyjnJ82I6F8mot/+7S7HZpt9HG0jPDbb7Js0IvpHAPwfAPyjAJ4A+BsB/FgA/wERjfd85i+b4d9ss80222yzzTb7hNofB/DfJ6IMAET0JoABwE/uXvsr7NqPzD7qPdm259tss4+HbYTHZpt9E0ZEjwH8FgC/VkT+PRGZReTLAP5uKOnxy+y630xEf4iI/lUiugDwK+y1fzXc6+8joq8Q0TMi+o1RshivDbLIX05EP0RET4noN4T7/BQi+l4ieklEbxHR776PePmAuv1MIvoqEf1viehdu9cvJKK/nYj+IhE9J6Jf/2GfS0Q/m4j+KyJ6RUT/HBF9T1STENH/lIj+SyJ6QUT/PhH92G+0zJttttlmm2222SfC/gyU4Pjr7O//AYD/CMB/1b32/SLydSL6lbZHuCSiHyCiXw0ARPQA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
gitextract_0vkho7vc/ ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── tests.yml ├── .travis.yml ├── LICENSE ├── README.md ├── README_cn.md ├── blind_watermark/ │ ├── __init__.py │ ├── att.py │ ├── blind_watermark.py │ ├── bwm_core.py │ ├── cli_tools.py │ ├── pool.py │ ├── recover.py │ ├── requirements.txt │ └── version.py ├── docs/ │ ├── .nojekyll │ ├── README.md │ ├── _coverpage.md │ ├── _navbar.md │ ├── _sidebar.md │ ├── en/ │ │ ├── README.md │ │ ├── _coverpage.md │ │ └── _sidebar.md │ ├── index.html │ ├── make_doc.py │ ├── run_server.bat │ ├── vue.css │ └── zh/ │ ├── README.md │ ├── _coverpage.md │ └── _sidebar.md ├── examples/ │ ├── example_bit.py │ ├── example_demo.ipynb │ ├── example_img.py │ ├── example_no_writing.py │ ├── example_str.py │ ├── example_str_multi.py │ └── output/ │ └── .keep ├── requirements.txt └── setup.py
SYMBOL INDEX (59 symbols across 9 files)
FILE: blind_watermark/att.py
function cut_att3 (line 9) | def cut_att3(input_filename=None, input_img=None, output_file_name=None,...
function resize_att (line 38) | def resize_att(input_filename=None, input_img=None, output_file_name=Non...
function bright_att (line 48) | def bright_att(input_filename=None, input_img=None, output_file_name=Non...
function shelter_att (line 60) | def shelter_att(input_filename=None, input_img=None, output_file_name=No...
function salt_pepper_att (line 83) | def salt_pepper_att(input_filename=None, input_img=None, output_file_nam...
function rot_att (line 98) | def rot_att(input_filename=None, input_img=None, output_file_name=None, ...
function cut_att_height (line 110) | def cut_att_height(input_filename=None, input_img=None, output_file_name...
function cut_att_width (line 124) | def cut_att_width(input_filename=None, input_img=None, output_file_name=...
function cut_att (line 138) | def cut_att(input_filename=None, output_file_name=None, input_img=None, ...
function anti_cut_att_old (line 177) | def anti_cut_att_old(input_filename, output_file_name, origin_shape):
function anti_cut_att (line 199) | def anti_cut_att(input_filename=None, input_img=None, output_file_name=N...
FILE: blind_watermark/blind_watermark.py
class WaterMark (line 14) | class WaterMark:
method __init__ (line 15) | def __init__(self, password_wm=1, password_img=1, block_shape=(4, 4), ...
method read_img (line 25) | def read_img(self, filename=None, img=None):
method read_wm (line 34) | def read_wm(self, wm_content, mode='img'):
method embed (line 56) | def embed(self, filename=None, compression_ratio=None):
method extract_decrypt (line 77) | def extract_decrypt(self, wm_avg):
method extract (line 83) | def extract(self, filename=None, embed_img=None, wm_shape=None, out_wm...
FILE: blind_watermark/bwm_core.py
class WaterMarkCore (line 14) | class WaterMarkCore:
method __init__ (line 15) | def __init__(self, password_img=1, mode='common', processes=None):
method init_block_index (line 32) | def init_block_index(self):
method read_img_arr (line 40) | def read_img_arr(self, img):
method read_wm (line 69) | def read_wm(self, wm_bit):
method block_add_wm (line 73) | def block_add_wm(self, arg):
method block_add_wm_slow (line 79) | def block_add_wm_slow(self, arg):
method block_add_wm_fast (line 96) | def block_add_wm_fast(self, arg):
method embed (line 106) | def embed(self):
method block_get_wm (line 140) | def block_get_wm(self, args):
method block_get_wm_slow (line 146) | def block_get_wm_slow(self, args):
method block_get_wm_fast (line 158) | def block_get_wm_fast(self, args):
method extract_raw (line 166) | def extract_raw(self, img):
method extract_avg (line 183) | def extract_avg(self, wm_block_bit):
method extract (line 190) | def extract(self, img, wm_shape):
method extract_with_kmeans (line 199) | def extract_with_kmeans(self, img, wm_shape):
function one_dim_kmeans (line 205) | def one_dim_kmeans(inputs):
function random_strategy1 (line 221) | def random_strategy1(seed, size, block_shape):
function random_strategy2 (line 227) | def random_strategy2(seed, size, block_shape):
FILE: blind_watermark/cli_tools.py
function main (line 19) | def main():
FILE: blind_watermark/pool.py
class CommonPool (line 9) | class CommonPool(object):
method map (line 10) | def map(self, func, args):
class AutoPool (line 14) | class AutoPool(object):
method __init__ (line 15) | def __init__(self, mode, processes):
method map (line 37) | def map(self, func, args):
FILE: blind_watermark/recover.py
class MyValues (line 8) | class MyValues:
method __init__ (line 9) | def __init__(self):
method set_val (line 13) | def set_val(self, image, template):
function match_template (line 22) | def match_template(w, h, idx):
function match_template_by_scale (line 30) | def match_template_by_scale(scale):
function search_template (line 37) | def search_template(scale=(0.5, 2), search_num=200):
function estimate_crop_parameters (line 66) | def estimate_crop_parameters(original_file=None, template_file=None, ori...
function recover_crop (line 88) | def recover_crop(template_file=None, tem_img=None, output_file_name=None...
FILE: blind_watermark/version.py
class Notes (line 4) | class Notes:
method __init__ (line 5) | def __init__(self):
method print_notes (line 8) | def print_notes(self):
method close (line 18) | def close(self):
FILE: docs/make_doc.py
function search_code (line 21) | def search_code(py_file_name, section_idx):
function make_doc (line 52) | def make_doc(origin_file):
FILE: setup.py
function read_file (line 9) | def read_file(filename):
function read_requirements (line 16) | def read_requirements(filename):
Condensed preview — 39 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (862K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 175,
"preview": "# These are supported funding model platforms\n\ncustom: [\"https://www.guofei.site/微信打赏.jpg\"]\nopen_collective: blind_water"
},
{
"path": ".github/workflows/tests.yml",
"chars": 861,
"preview": "name: test all\n\non: [ push, pull_request ]\n\njobs:\n build:\n runs-on: ubuntu-latest\n name: Test python API\n defa"
},
{
"path": ".travis.yml",
"chars": 517,
"preview": "language: python\npython:\n - \"3.8\"\n\n\n# command to install dependencies\ninstall:\n - pip install -r requirements.txt\n - "
},
{
"path": "LICENSE",
"chars": 1059,
"preview": "MIT License\n\nCopyright (c) 2019 郭飞\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this"
},
{
"path": "README.md",
"chars": 5691,
"preview": "\n\n\n# blind-watermark\n\nBlind watermark based on DWT-DCT-SVD.\n\n\n[](h"
},
{
"path": "README_cn.md",
"chars": 4887,
"preview": "# blind-watermark\n\n基于频域的数字盲水印 \n\n\n[](https://pypi.org/project/blin"
},
{
"path": "blind_watermark/__init__.py",
"chars": 171,
"preview": "from .blind_watermark import WaterMark\nfrom .bwm_core import WaterMarkCore\nfrom .att import *\nfrom .recover import recov"
},
{
"path": "blind_watermark/att.py",
"chars": 8009,
"preview": "# coding=utf-8\n\n# attack on the watermark\nimport cv2\nimport numpy as np\nimport warnings\n\n\ndef cut_att3(input_filename=No"
},
{
"path": "blind_watermark/blind_watermark.py",
"chars": 3915,
"preview": "#!/usr/bin/env python3\n# coding=utf-8\n# @Time : 2020/8/13\n# @Author : github.com/guofei9987\nimport warnings\n\nimport "
},
{
"path": "blind_watermark/bwm_core.py",
"chars": 8941,
"preview": "#!/usr/bin/env python3\n# coding=utf-8\n# @Time : 2021/12/17\n# @Author : github.com/guofei9987\nimport numpy as np\nfrom"
},
{
"path": "blind_watermark/cli_tools.py",
"chars": 2023,
"preview": "from optparse import OptionParser\nfrom .blind_watermark import WaterMark\n\nusage1 = 'blind_watermark --embed --pwd 1234 i"
},
{
"path": "blind_watermark/pool.py",
"chars": 1077,
"preview": "import sys\nimport multiprocessing\nimport warnings\n\nif sys.platform != 'win32':\n multiprocessing.set_start_method('for"
},
{
"path": "blind_watermark/recover.py",
"chars": 3352,
"preview": "import cv2\nimport numpy as np\n\nimport functools\n\n\n# 一个帮助缓存化加速的类,引入事实上的全局变量\nclass MyValues:\n def __init__(self):\n "
},
{
"path": "blind_watermark/requirements.txt",
"chars": 15,
"preview": "blind-watermark"
},
{
"path": "blind_watermark/version.py",
"chars": 529,
"preview": "__version__ = '0.4.4'\n\n\nclass Notes:\n def __init__(self):\n self.show = True\n\n def print_notes(self):\n "
},
{
"path": "docs/.nojekyll",
"chars": 0,
"preview": ""
},
{
"path": "docs/README.md",
"chars": 1802,
"preview": "\n# [blind_watermark](https://github.com/guofei9987/blind_watermark)\n\n[ -->\n\n# blind_watermark\n\n> 数字盲水印\n\n* 图片水印\n* 比特水印\n\n[GitHub](https://github.com/guofei9987/blin"
},
{
"path": "docs/_navbar.md",
"chars": 60,
"preview": "- Translations\n - [:uk: English](/en/)\n - [:cn: 中文](/zh/)\n"
},
{
"path": "docs/_sidebar.md",
"chars": 55,
"preview": "\n* [English Document](docs/en.md)\n* [中文文档](docs/zh.md)\n"
},
{
"path": "docs/en/README.md",
"chars": 5998,
"preview": "\n# blind-watermark\n\nBlind watermark based on dct and svd.\n\n\n[](htt"
},
{
"path": "docs/en/_coverpage.md",
"chars": 1351,
"preview": "\n\n# blind_watermark\n\n> Blind Watermark\n\n* [](https://pypi.org/proj"
},
{
"path": "docs/en/_sidebar.md",
"chars": 28,
"preview": "* [Document](en/README.md)\n\n"
},
{
"path": "docs/index.html",
"chars": 1646,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>blind_watermark</title>\n <meta http-equ"
},
{
"path": "docs/make_doc.py",
"chars": 3158,
"preview": "# 不想用 Sphinx,也不像弄一堆静态html文件,所以自己写个咯\n\n\n'''\n需要从readme中解析出:\n1. \"-> Demo code: [examples/demo_pso.py](examples/demo_pso.py)\""
},
{
"path": "docs/run_server.bat",
"chars": 13,
"preview": "docsify serve"
},
{
"path": "docs/vue.css",
"chars": 15938,
"preview": "@import url(\"https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600\");\n\n* {\n -webkit-font-sm"
},
{
"path": "docs/zh/README.md",
"chars": 5487,
"preview": "# blind-watermark\n\n基于频域的数字盲水印 \n\n\n[](https://pypi.org/project/blin"
},
{
"path": "docs/zh/_coverpage.md",
"chars": 1333,
"preview": "<!--  -->\n\n# blind_watermark\n\n> 数字盲水印\n\n* []"
},
{
"path": "docs/zh/_sidebar.md",
"chars": 22,
"preview": "* [文档](zh/README.md)\n\n"
},
{
"path": "examples/example_bit.py",
"chars": 3500,
"preview": "# -*- coding: utf-8 -*-\n# -*- coding: utf-8 -*-\n\nfrom blind_watermark import att\nfrom blind_watermark import WaterMark\ni"
},
{
"path": "examples/example_demo.ipynb",
"chars": 758116,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 6,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n "
},
{
"path": "examples/example_img.py",
"chars": 586,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\nimport cv2\n\nfrom blind_watermark import WaterMark\nimport os\n\nos.chdir(os."
},
{
"path": "examples/example_no_writing.py",
"chars": 6464,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\nThis demonstrates how to embed and extract without writing files to l"
},
{
"path": "examples/example_str.py",
"chars": 6739,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# embed string\nimport numpy as np\nfrom blind_watermark import WaterMark\nf"
},
{
"path": "examples/example_str_multi.py",
"chars": 1493,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n'''\ndemonstrate multiprocessing and multithreading\n'''\n# embed string\nfro"
},
{
"path": "examples/output/.keep",
"chars": 0,
"preview": ""
},
{
"path": "requirements.txt",
"chars": 50,
"preview": "numpy>=1.17.0\nopencv-python\nsetuptools\nPyWavelets\n"
},
{
"path": "setup.py",
"chars": 1204,
"preview": "from setuptools import setup, find_packages\nfrom os import path as os_path\nimport blind_watermark\n\nthis_directory = os_p"
}
]
About this extraction
This page contains the full source code of the guofei9987/blind_watermark GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 39 files (836.4 KB), approximately 545.9k tokens, and a symbol index with 59 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.