LSB是空域数字水印的一项技术,顾名思义就是在图片的每个像素的最低位上嵌入水印信息。
介绍原理的博客资料网上很多,说点不一样的。
一开始学习的时候在网上看了一个讲解的python实现
此文中的大致意思是将水印图片二值化插入到原图中的像素的最后一位(首先将原图像素的最后一位置零)
用此方法实现:
原图
加水印后图
原水印
提取出的水印图片
可以看出原图与加水印后的图别无二样。
但是这样的弊端是只能存储二值化后的图片,虽然可以一定程度的避开RS(Regular Singular)隐写分析技术。这个下篇博客会讲到。
更常规的LSB算法应该是像此文中所言,将所需要存储的信息转化为二进制存储在数字图像中。
例如:一个若干字节的音频信息(当然也可以是图片,可能字节数多一点罢了) 这里举一个字节的例子(太懒了)133转化为二进制是八位(一个字节)10000101 这八位可以放在图像的八个像素点的最后一位上。
当然这样的话RS(Regular Singular)分析可以轻易的得出隐写率。当然直观上会更隐蔽,存储的信息也不限于二值化的图片,但是存储的总信息量是不变的。
可能有人有疑问为啥第一种方法可以一定程度上避开RS分析,这个问题困惑了好几天,个人认为因为二值化的图片像素间的具有一定的平滑性,相较于第二种随机性弱许多,破坏了RS分析所需要的统计假设。(PS:有大佬懂这个可以详细解释一下)
这里贴上第一种实现的代码,第二种也比较简单,对需要加的水印信息二进制话再插入就行。
这里实现的是RGB三通道的单像素8bit的图,也可以用灰度图,RGB转灰度图的代码下面也给出。(程序中的图片自备)
def rgb2gray(rgb):
r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
return np.trunc(gray)#np.trunc对矩阵取整
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 11:43:12 2020
@author: MYM
"""
import matplotlib.pyplot as plt
import matplotlib.image as pmg
import numpy as np
#读入图像
limit=200#二值化临界值
cr="copytest.jpg"#copyright.jpg
copy_right=pmg.imread(cr)
origin=pmg.imread("lena.bmp")
if copy_right.shape[0] > origin.shape[0] or \
copy_right.shape[1] > origin.shape[1]:
raise ValueError("copyright image must be smaller than original image")
#显示读入的图像
plt.imshow(copy_right)
plt.title("copyright_picture")
plt.axis('off')
plt.figure()
plt.imshow(origin)
plt.axis('off')
plt.title("origin_picture")
#图片备份
watermark=origin.copy()
copyrig=copy_right.copy()
#对版权图片二值化
for m in range(3):
for i in range(copyrig.shape[0]):
for j in range(copyrig.shape[1]):
if copyrig[i,j,m]>limit:
copyrig[i,j,m]=1
else:
copyrig[i,j,m]=0
#对原图最小位置零
for i in range(0,watermark.shape[0]):
for j in range(0,watermark.shape[1]):
watermark[i,j,:]=(watermark[i,j,:]//2)*2 #//取整除运算符
#将二值化的版权图片加入原图中
h,w=copyrig.shape[0],copyrig.shape[1]
watermark[0:h,0:w,:]=watermark[0:h,0:w,:]+copyrig
#显示加水印后的图像
plt.figure()
plt.imshow(watermark)
plt.axis('off')
plt.title("watermark")
#提取加水印图像的信息
c_watermark=watermark.copy()
watermark_copyright=(c_watermark%2)*255
#显示提取出的水印信息
plt.figure()
plt.imshow(watermark_copyright)
plt.axis('off')
plt.title("watermark_copyright")