3.8数字水印
最低有效位:指的是一个二进制数中的第0位(最低有效位)。
最低有效位信息隐藏:将一个需要隐藏的二值图像信息嵌入载体图像的最低有效位,
原理:
嵌入过程:将载体图像的第0个位平面替换为数字水印信息(一幅二值图像)
提取过程:将载体图像的最低有效位所构成的第0个位平面提取出来,得到数字水印信息。
1. 嵌入过程
原始载体图像预处理
将原始图像处理为二进制,并标记出最低有效位
水印图像处理
在嵌入水印前,需要将水印信息处理为二值图像,将灰度二值水印信息进行阈值处理。
嵌入水印
将载体图像的最低有效位替换为二进制水印图像,完成水印的嵌入
2. 提取过程
提取过程是指将水印信息从包含水印信息的载体图像内提取出来的过程,提取水印时,先将含水印载体图像的像素值转换为二进制,然后从其最低有效位提取出水印信息即可。
实现方法:
1. 嵌入过程
(1)载体图像预处理
读取原始载体图像O,并获取载体图像的行数N和列数M,将其标记对应的二进制形式OB
(2)建立提取矩阵
建立一个M*N大小,元素值均为254的提取矩阵(数组),用来提取载体图像的高七位。
(3)保留载体图像的高七位,将最低位置0
需要将载体图像与元素值均为254的提取矩阵进行按位与运算。
(4)水印图像处理
当水印图像为8位灰度图的二值图像时,就需要将其转换为二进制二值图像,将其中的像素值255转换为像素值1
(5)嵌入水印
将原始载体图像进行“保留高七位、最低位置0”的操作后,得到一副新的图像,将新图像与水印图像进行按位或运算,就能实现将水印信息嵌入原始载体图像内的效果。
(6)显示图像
完成上述处理后,分别显示原始载体图像、水印图像、含水印图像
2. 提取过程
(1)含水印载体图像处理
读取包含水印的载体图像,获取含水印载体图像的大小M*N
(2)建立提取矩阵
定义一个与含水印载体图像等大小的值为1的矩阵(数组)作为提取矩阵
(3)提取水印信息
将含水印载体图像与提取矩阵进行按位与运算,提取水印信息。
(4)计算去除水印后的载体图像
有时需要删除包含在水印载体图像内的水印信息,通过将含水印载体图像的最低有效位置零,即可实现删除水印信息。
通过将含有水印载体图像WO与TB进行按位与运算,即可将载体图像WO的最低有效位置零,得到删除水印信息的载体图像ODW。
(5)显示图像
根据需要,分别显示提取出来的水印图像WG、删除水印信息的载体图像ODW。
#3.15编写程序,模拟数字水印的嵌入和提取过程
import cv2
import numpy as np
#读取原始载体图像
lena=cv2.imread("lena.bmp",0)
#读取水印图像
watermark=cv2.imread("watermark.bmp",0)
#将水印内的255处理为1,以方便嵌入
#后续章节会介绍使用threshold处理。
w=watermark[:,:]>0
watermark[w]=1
#读取原始载体图像的shape值
r,c=lena.shape
#============嵌入过程============
#生成内部值都是254的数组
t254=np.ones((r,c),dtype=np.uint8)*254
#获取lena图像的高7位
lenaH7=cv2.bitwise_and(lena,t254)
#将watermark嵌入到lenaH7内
e=cv2.bitwise_or(lenaH7,watermark)
#============提取过程============
#生成内部值都是1的数组
t1=np.ones((r,c),dtype=np.uint8)
#从载体图像内,提取水印图像
wm=cv2.bitwise_and(e,t1)
print(wm)
#将水印内的1处理为255以方便显示
#后续章节会介绍threshold实现。
w=wm[:,:]>0
wm[w]=255
#============显示============
cv2.imshow("lena",lena)
cv2.imshow("watermark",watermark*255) #当前watermark内最大值为1
cv2.imshow("e",e)
cv2.imshow("wm",wm)
cv2.waitKey()
cv2.destroyAllWindows()
#3.16编写程序,使用掩码对lena图像的脸部进行打码、解码
import cv2
import numpy as np
#读取原始载体图像
lena=cv2.imread("lena.bmp",0)
#读取原始载体图像的shape值
r,c=lena.shape
mask=np.zeros((r,c),dtype=np.uint8)
mask[220:400,250:350]=1
#获取一个key,打码、解码所使用的密钥
key=np.random.randint(0,256,size=[r,c],dtype=np.uint8)
#============获取打码脸============
#使用密钥key加密原始图像lena
lenaXorKey=cv2.bitwise_xor(lena,key)
#获取加密图像的脸部信息encryptFace
encryptFace=cv2.bitwise_and(lenaXorKey,mask*255)
#将图像lena内的脸部值设置为0,得到noFace1
noFace1=cv2.bitwise_and(lena,(1-mask)*255)
#得到打码的lena图像
maskFace=encryptFace+noFace1
#============将打码脸解码============
#将脸部打码的lena与密钥key异或,得到脸部的原始信息
extractOriginal=cv2.bitwise_xor(maskFace,key)
#将解码的脸部信息extractOriginal提取出来得到extractFace
extractFace=cv2.bitwise_and(extractOriginal,mask*255)
#从脸部打码的lena内提取没有脸部信息的lena图像,得到noFace2
noFace2=cv2.bitwise_and(maskFace,(1-mask)*255)
#得到解码的lena图像
extractLena=noFace2+extractFace
#============显示图像============
cv2.imshow("lena",lena)
cv2.imshow("mask",mask*255)
cv2.imshow("1-mask",(1-mask)*255)
cv2.imshow("key",key)
cv2.imshow("lenaXorKey",lenaXorKey)
cv2.imshow("encryptFace",encryptFace)
cv2.imshow("noFace1",noFace1)
cv2.imshow("maskFace",maskFace)
cv2.imshow("extractOriginal",extractOriginal)
cv2.imshow("extractFace",extractFace)
cv2.imshow("noFace2",noFace2)
cv2.imshow("extractLena",extractLena)
cv2.waitKey()
cv2.destroyAllWindows()
#图层提取
import cv2
import numpy as np
lena=cv2.imread("lena.bmp",0)
cv2.imshow("lena",lena)
r,c=lena.shape
x=np.zeros((r,c,8),dtype=np.uint8)
for i in range(8):
x[:,:,i]=2**i
r=np.zeros((r,c,8),dtype=np.uint8)
for i in range(8):
r[:,:,i]=cv2.bitwise_and(lena,x[:,:,i])
mask=r[:,:,i]>0
r[mask]=255
cv2.imshow(str(i),r[:,:,i])
cv2.waitKey()
cv2.destroyAllWindows()

