[Opencv基础]水印,数字水印,频域水印(隐形水印)

水印,你在很多公司图片都会看到,里面都会加入图片都会有显式水印,或者半隐形水印。
平常加水印,只要将两张图片色值混合就没问题了

import cv2
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
img  = cv2.imread("lena.jpg")
img= cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
wm = cv2.imread("cang_wang.png")
wm = cv2.resize(wm,(364,40))
# wm = 255-wm
img1 = cv2.resize(img,(600,600))
//圈定感兴趣区域
imgROI = img1[600-wm.shape[0]:600,600-wm.shape[1]:600]
//图片透明度混合
cv2.addWeighted(imgROI,0.5,wm,0.5,0,imgROI)
plt.figure(figsize=(11,11))
plt.imshow(img1)

在这里插入图片描述
这里引用到Opencv 图像叠加 添加水印

数字水印是怎样的?
1、预处理隐藏信息
首先将需要加密的图像进行转换为二值图像,其中只包含两个灰度级0和1。其中0对应黑色,1对应白色。在opencv中其实没有二值图像,我们可以将二值图像理解为特殊的灰度图像。由于需要将隐藏信息嵌入图片的第0位(每个像素点分出一个bit位来存储信息)所以被隐藏信息图像的最高灰度级必须为1,最低为0。

对图像进行二值化可以利用以下方法:

s_black = s[:,:]<128 # s为需要被隐藏的图片 s_black记录灰度值小于128的像素的位置
s[s_black] = 0 # 将灰度值小于128的灰度值置为0
s_white = s[:]>=128 # s_white记录灰度值大于128的像素的位置
s[s_white] = 1 # 将灰度值大于128的灰度值置为1
这样就得到被标记为0和1的矩阵

彩色图片色值0~255,我们可以借用RGB其中一个色值,然后转为二进制值,最后一位用来记录签名值。因为最后一位色值其实变化很小,用来记录二值化干扰非常小。

# 因为没有现成的二值图像,在此的s图像是一个包含黑色和白色的彩色图像,因此在这里需要阈值化处理
#这里水印图设置成原图大小,不然不能使用与或运算,如果有人知道抽取roi区域做与或运算的方法也可以告诉我
wm_2 = cv2.resize(wm,(img.shape[1],img.shape[0]))
plt.imshow(wm_2)
s_black = wm_2[:,:]<128
wm_2[s_black] = 1
s_white = wm_2[:]>=128
wm_2[s_white] = 0

# r, c = img.shape
r = img.shape[0]
c = img.shape[1]
 
# 构造提取原始图像高7位矩阵
t255 = np.ones((r, c, 3), dtype=np.uint8)*254
 
# # 获取原始图像的高七位
demo_h7 = np.bitwise_and(img, t255)
# plt.imshow(demo_h7)
 
# # 嵌入水印
demo_s_in = np.bitwise_or(demo_h7, wm_2)
# plt.imshow(cv2.hconcat([demo_h7,demo_s_in]))
 
# 生成提取矩阵
t1 = np.ones((r, c, 3), dtype=np.uint8)
s_out = np.bitwise_and(demo_s_in, t1)
s_out_white = s_out[:]<1
s_out[s_out_white] = 255
# cv2.imshow("s_out", s_out)
plt.figure(figsize=(11,11))
plt.imshow(cv2.hconcat([demo_h7,demo_s_in,s_out]))

在这里插入图片描述
在这里插入图片描述
可以看出加了水印的图,其实和原图没有太大的差别。
因为我本来水印图色值还是有拉伸的,直接转化为0,1两个数字后,再和原图或值合并。
所以还原回来看水印的还原还是有区域无法正常显示。

数字水印的方式,其实抗干扰性非常之差,稍微进行

这里应用OpenCv图像处理——数字水印

频域水印
所谓频域水印,首先需要了解傅里叶变换

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('lena.jpg',0) #直接读为灰度图像
img = cv2.resize(img,(300,300))

wm = cv2.imread("cang_wang.png", 0)
wm = cv2.resize(wm,(200,50))
wm = 255-wm

#快速傅里叶变换算法得到频率分布
f = np.fft.fft2(img)
#默认结果中心点位置在左上角,转移到中间
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到0-255
#fshift是复数,求绝对值结果才是振幅
s1 = np.log(np.abs(fshift))

#求相位,相位和振幅是频域两个很重要的结果
#振幅只是记录图片的明暗,而相位才是记录图像的形状
s1_angle = np.angle(fshift)

#将水印放入频域
fshift2 = fshift.copy()
fshift2[0:50, 0:200] += wm *50.0
fshift2[-50:, -200:] += cv2.flip(wm, -1) *50.0

s2 = np.log(np.abs(fshift2))

# 逆变换
f1shift2 = np.fft.ifftshift(fshift2)
img_back2 = np.fft.ifft2(f1shift2)
#出来的复数,无法显示,转成实数
img_back2 = np.abs(img_back2)

f1shift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f1shift)
#出来的是复数,无法显示
img_back = np.abs(img_back)
plt.figure()
plt.imshow(img,'gray')
plt.figure()
plt.imshow(wm, 'gray')
plt.figure()
plt.imshow(s1,'gray')
plt.figure()
plt.imshow(s2,'gray')
plt.figure()
plt.imshow(img_back,'gray')

plt.figure()
plt.imshow(img_back2,'gray')

原图
在这里插入图片描述
水印图
在这里插入图片描述
频域图
在这里插入图片描述
加水印后频域图
在这里插入图片描述
频域逆转换后图
在这里插入图片描述
频域加水印后逆转换后图
在这里插入图片描述
关于opencv使用傅里叶变换,可以参照一下这个文章OpenCV学习笔记-傅里叶变换
关于频域水印再受到变换后可能出现的问题,可以参照这篇文章有意思的数字盲水印的简单的实现
基本旋转平移、光暗调整等操作,不会对水印有太大影响,但是通过模糊算法后,水印会被刷除,但是锐化算法不会有太大影响。

MIT 6.824 课程的 Lab1 是关于 Map 的实现,这里单介绍一下实现过程。 MapReduce 是一种布式计算模型,它可以用来处理大规模数据集。MapReduce 的核心想是将数据划分为多个块,每个块都可以在不同的节点上并行处理,然后将结果合并在一起。 在 Lab1 中,我们需要实现 MapReduce 的基本功能,包括 Map 函数、Reduce 函数、分区函数、排序函数以及对作业的整体控制等。 首先,我们需要实现 Map 函数。Map 函数会读取输入文件,并将其解析成一系列键值对。对于每个键值对,Map 函数会将其传递给用户定义的 Map 函数,生成一些新的键值对。这些新的键值对会被分派到不同的 Reduce 任务中,进行进一步的处理。 接着,我们需要实现 Reduce 函数。Reduce 函数接收到所有具有相同键的键值对,并将它们合并成一个结果。Reduce 函数将结果写入输出文件。 然后,我们需要实现分区函数和排序函数。分区函数将 Map 函数生成的键值对映射到不同的 Reduce 任务中。排序函数将键值对按键进行排序,确保同一键的所有值都被传递给同一个 Reduce 任务。 最后,我们需要实现整个作业的控制逻辑。这包括读取输入文件、调用 Map 函数、分区、排序、调用 Reduce 函数以及写入输出文件。 Lab1 的实现可以使用 Go 语言、Python 或者其他编程语言。我们可以使用本地文件系统或者分布式文件系统(比如 HDFS)来存储输入和输出文件。 总体来说,Lab1 是一个比较简单的 MapReduce 实现,但它奠定了 MapReduce 的基础,为后续的 Lab 提供了良好的基础
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值