結(jié)合Arnold變換的基于DWT的數(shù)字水印的嵌入。充分利用了小波變換的特點,采用Haar小波,把原始圖像及水印圖像進行三級小波分解,然后在多分辨率分解后的頻段嵌入水印信號,得到嵌入水印的圖像。
數(shù)字水印最重要的性質(zhì)就是魯棒性和不可感知性,兩者存在一定的矛盾。魯棒性要求加大水印信息的強度,而水印信息強度的增大反過來又會影響水印的不可感知性,因此必須權(quán)衡這兩方面的性質(zhì),達到魯棒性和不可感知性的平衡。圖像的邊緣和紋理部分能隱藏較大的數(shù)據(jù)量,而圖像的平坦部分對噪聲相對敏感。由多分辨率分析的思想,圖像平坦的部分集中了圖像絕大部分的能量,對應(yīng)著小波變換后的低頻子帶。而高頻部分則對應(yīng)于圖像的邊緣和紋理,即細節(jié)部分。若考慮水印的魯棒性,應(yīng)將水印信息嵌入到圖像的低頻子帶,但低頻段的變化對人眼的視覺影響較大,很難兼顧重構(gòu)圖像的不可感知性。若將水印信息嵌入高頻子帶,可以很好地將水印隱藏,但這樣的水印卻無法抵抗有損壓縮、低通濾波等簡單的圖像處理。因此,如果能在水印嵌入時充分結(jié)合高、低頻的特性,就有可能得效果較好的水印嵌入方法。
綜合以上考慮,本文中的算法采用水印信息多分辨率重復(fù)嵌入思想。首先將水印圖像進行Arnold 置亂,然后將原始圖像進行三級離散小波分解后的系數(shù)進行排序分組,并針對不同分組,采用不同強度的嵌入系數(shù),進行相應(yīng)水印分解子圖的重復(fù)嵌入。各子圖分組數(shù)目即為水印重復(fù)嵌入的次數(shù)。
水印嵌入算法的步驟如下:
①分別讀取原始圖像X和水印圖像W。
②對水印圖像W進行k次Arnold變換,將置亂后的水印記為W。并將系數(shù)與變換次數(shù)作為密鑰key 保存。
③對置亂后的水印 Wa 采用Haar小波進行一級小波分解,得到一級分辨率下的一個逼近子圖cal和三個細節(jié)子圖chl,cvl,cd1。
④將原始圖像X采用Haar小波進行三級小波分解,得到不同分辨率級下的多個細節(jié)子圖和一個逼近子圖,具體分解子圖為: cA3,cH3,cV3,cD3,cH 2,cV2,cD2,cH 1,cV1,cD1 。
⑤將 Wa 一級小波分解后的各子圖分別嵌入原始圖像第三級小波分解后的對應(yīng)子圖中,不同的分組選取不同的系數(shù):
水印的提取過程其實是嵌入過程的逆過程,具體步驟如下:
①分別讀入原始圖像X和已嵌入水印的圖像XW。
②將原始圖像X和已嵌入水印的圖像XW分別采用 Haar小波進行三級小波分解,分別得到不同分辨率級下的多個細節(jié)子圖和一個逼近子圖。
③用cA3和 cA3 ', cH3和cH3’, cV3和 cV3’,cD3和 cD3’進行嵌入算法的逆運算提取水印圖像一級分解的子圖: ca1,ch1,cv1,cd1,對提取的小波系數(shù)進行一級小波逆變換,得到水印置亂變換后的圖像。
④根據(jù)嵌入時的密鑰key進行Arnold反變換,得到提取出的水印W。
"""-------------------------
Project: DWT數(shù)字水印嵌入、提取
Editor: PlanetRT
Environment: Python3.8 + Pycharm
Time: 2021/09/30
-------------------------"""
import cv2
import pywt
import numpy as np
# arnold置換算法,key位置換次數(shù)
def arnold(img,key):
r = img.shape[0]
c = img.shape[1]
p = np.zeros((r,c),np.uint8)
a = 1
b = 1
for k in range(key):
for i in range(r):
for j in range(c):
x = (i + b * j) % r
y = (a * i + (a * b + 1) * j) % c
p[x,y] = img[i,j]
return p
# 逆arnold置換算法,key位置換次數(shù)
def deArnold(img,key):
r = img.shape[0]
c = img.shape[1]
p = np.zeros((r,c),np.uint8)
a = 1
b = 1
for k in range(key):
for i in range(r):
for j in range(c):
x = ((a * b + 1) * i - b * j) % r
y = (-a * i + j) % c
p[x,y] = img[i,j]
return p
def setwaterMark(waterTmg,Img,key):
print('水印嵌入...')
Img = cv2.resize(Img,(400,400))
waterTmg = cv2.resize(waterTmg,(201,201))
# 載體圖像灰度處理
Img1 = cv2.cvtColor(Img,cv2.COLOR_RGB2GRAY)
waterTmg1 = cv2.cvtColor(waterTmg,cv2.COLOR_RGB2GRAY)
# 對水印圖像進行Arnold變換
waterTmg1 = arnold(waterTmg1,key)
cv2.imshow('ds',Img1)
cv2.waitKey(0)
# 載體圖像三級小波變換
c = pywt.wavedec2(Img1,'db2',level=3)
[cl,(cH3,cV3,cD3),(cH2,cV2,cD2),(cH1,cV1,cD1)] = c
# 水印圖像一級小波變換
waterTmg1 = cv2.resize(waterTmg1,(101,101))
cv2.imshow('img',waterTmg1)
cv2.waitKey(0)
d = pywt.wavedec2(waterTmg1,'db2',level=1)
[ca1,(ch1,cv1,cd1)] = d
# 自定義嵌入系數(shù)
a1 = 0.1
a2 = 0.2
a3 = 0.1
a4 = 0.1
# 嵌入
cl = cl + ca1 * a1
cH3 = cH3 + ch1 * a2
cV3 = cV3 + cv1 * a3
cD3 = cD3 + cd1 * a4
# 圖像重構(gòu)
newImg = pywt.waverec2([cl,(cH3,cV3,cD3),(cH2,cV2,cD2),(cH1,cV1,cD1)],'db2')
newImg = np.array(newImg,np.uint8)
print('水印嵌入完成!')
cv2.imshow("after",newImg)
cv2.imwrite('./after.bmp',newImg)
cv2.waitKey(0)
def getwaterMark(originalImage,Img,key):
print('水印提取...')
# 原始圖像灰度處理
originalImage = cv2.resize(originalImage,(400,400))
Img1 = cv2.cvtColor(originalImage,cv2.COLOR_RGB2GRAY)
Img = cv2.cvtColor(Img,cv2.COLOR_RGB2GRAY)
cv2.imshow('ds',Img1)
cv2.waitKey(0)
# 載體圖像三級小波變換
c = pywt.wavedec2(Img,'db2',level=3)
[cl,(cH3,cV3,cD3),(cH2,cV2,cD2),(cH1,cV1,cD1)] = c
# 原始圖像三級小波變換
d = pywt.wavedec2(Img1,'db2',level=3)
[dl,(dH3,dV3,dD3),(dH2,dV2,dD2),(dH1,dV1,dD1)] = d
# 嵌入算法逆運算
# 自定義嵌入系數(shù)
a1 = 0.1
a2 = 0.2
a3 = 0.1
a4 = 0.1
# 提取
print(cl.shape)
print(dl.shape)
ca1 = (cl - dl) * 10
ch1 = (cH3 - dH3) * 5
cv1 = (cV3 - dV3) * 10
cd1 = (cD3 - dD3) * 10
# 水印圖像重構(gòu)
waterImg = pywt.waverec2([ca1,(ch1,cv1,cd1)],'db2')
waterImg = np.array(waterImg,np.uint8)
cv2.imshow("get",waterImg)
cv2.waitKey(0)
# 對提取的水印圖像進行逆Arnold變換
waterImg = deArnold(waterImg,key)
print('水印提取完成!')
cv2.imshow("get",waterImg)
cv2.imwrite('./getWater.bmp',waterImg)
cv2.waitKey(0)
if __name__ == '__main__':
# 讀取水印圖像、載體圖像
waterImg = cv2.imread('./O.bmp')
Img = cv2.imread('./OIP-C.bmp')
# 水印嵌入
setwaterMark(waterImg,Img,10)
# 讀取原始圖像、嵌入水印圖像
originalImage = cv2.imread('./OIP-C.bmp')
Img = cv2.imread('./after.bmp')
# 水印提取
getwaterMark(originalImage,Img,10)
聯(lián)系客服