差异扩展(difference expance )可逆水印算法总结

一、前言

        最近在实验个很早就提出来的差异扩展(difference expance )可逆水印,将水印信息嵌入至图像,再做完好提取以及完好恢复图像。

二、原理

        (1)嵌入过程

        图像中取一对像素相邻对(x,y),可以水平相邻,也可以垂直相邻

        计算均值 l = [ (x+y )/2 ]  ,  差值 h = x-y , 中括号为取整运算

        假设要隐藏的二值信息为 b , b为0 或 1

        则计算  hs = 2*h+b 

        接着需要判断 hs 和 l  还原出来的值有没溢出超过0 或 255, 只需判断 hs 属不属于[ 0 , min(2(255-l) , 2l+1)] , 如果属于的话,则为可扩展,再计算出嵌入好信息的 xs,ys,公式(1)为

        xs = l+[(hs+l)/2],ys=l-[hs/2 ]   |  hs>=0

        ys = l+[hs/2],ys=l-[(hs-1)/2]      |  hs<0         

         如果上面不属于,则是不可扩展,再使用直接改变lsb的形式,需要先记下原先的lsb位,例入 11%2 =1 , lsb(11) = 1

        令 d = lsb(h) , 再计算 hs = 2*[ h/2]+b , 这个实际直接改变了 h的 lsb位

        然后再判读hs 是否属于[ 0 , min(2(255-l) , 2l+1)] ,  属于的话,则为可改变,同样计算公式(1)可得到嵌入好信息的 xs,ys

         (2)提取过程

         提取的话,假设嵌入好信息的像素对为 xs,ys , 同样计算均值和差值:

                均值 l = [ (xs+ys )/2 ]  ,  差值 hs = xs-ys , 中括号为取整运算

                首先提取水印信息,只需将 hs 对2求余数, b = hs%2                 

                然后如果为可扩展的嵌入方式,则恢复真实差值

                                h = ( hs-b)/2

                如果为可改变的嵌入方式,则恢复真实差值,下面的 d 是在嵌入过程需要保存起来的,是真实lsb位

                                h =  hs-b+d

                再依据公式(1) ,由 l 和 h 计算出 恢复的 x , y ,如下:

                        x = l+[(h+l)/2],y=l-[h/2 ]   |  h>=0

                        y = l+[h/2],y=l-[(h-1)/2]      |  h<0   

         这样就可以得到提取的水印二值信息 b , 和 恢复出来的 x,y

三、代码

# -*- coding: utf-8 -*-
"""
Created on Tue Nov  9 18:19:45 2021

"""

import cv2
import numpy as np


def test():

    img = cv2.imread( "butterfly.png" )
    gray = cv2.cvtColor( img , cv2.COLOR_BGR2GRAY)
    
    h,w = gray.shape[:2]
    for r in range(h):
        for c in range(w):
            #print(  gray[ r , c ] )
            pass
    
    cv2.imshow("src" , gray )  
    cv2.waitKey()        
    cv2.destroyAllWindows()   

n = 2000
p = np.random.randint( 0 , 2 , n) #嵌入的信息, 0,1 交替的序列,n为长度


info_p = []
info_a = []


def convHL( h, l ):
    if h>=0:
        x = l+int( ( h+1 )/2 )    
        y = l-int( h/2 )
    else:
        x = l+int( ( h  )/2 )    
        y = l-int( (h-1)/2 )  
    return x, y

def embedMsg():
    print( "嵌入的信息:" , p )

    img = cv2.imread( "butterfly.png" )
    img = cv2.cvtColor( img , cv2.COLOR_BGR2GRAY)    
    img_src = img.copy()
    H,W = img.shape[:2]
    img_data = img.reshape(-1)
    
    loc_1 = []
    loc_2 = []
    lsb_2 = { }
    for i in range( n ):
        x = img_data[2*i]*1.0 
        y =  img_data[2*i+1]*1.0 
        
        h = x-y
        l = int((x+y)/2)
        hs_1 = 2*h+p[i]   #可扩展
        hs_2 = 2*int( h/2 ) + p[i]  #不可扩展,可改变,直接改变lsb位
        
        if abs( hs_1 ) <= min( 2*(255-l)  ,2*l+1  ):
            xs,ys = convHL( hs_1, l )
            loc_1.append(  2*i )
        elif abs( hs_2 ) <= min( 2*(255-l)  ,2*l+1  ):
            xs,ys = convHL( hs_2, l )
                  
            loc_2.append(  2*i )
            lsb_2[ 2*i ] = int(h)%2  #原来的lsb位
        else:
            print( "no_type" )
            
        img_data[2*i] = xs 
        img_data[2*i+1] = ys       
        
        global info_p
        info_p.append( [ x , y ,  p[i]] )
        
    out = img_data.reshape( H,W  )  
    cv2.imshow("src" , img_src ) 
    cv2.imshow("embed_img" , out )    

    return loc_1 ,  loc_2 ,lsb_2 , out,img_src


def extractMsg( loc_1 , loc_2 , lsb_2 , img_emd ):
    H,W = img_emd.shape[:2]
    img_data = img_emd.copy().reshape(-1)
    n = len(loc_1+ loc_2)
     
    p_ext = []
    
    for i in range( n ):
        loc = 2*i
        xs = img_data[2*i]*1.0
        ys = img_data[2*i+1]*1.0
        
        hs = xs-ys
        ls = int( (xs + ys)/2)  
        b = int( hs%2 )
        
        if loc in loc_1:  #属于可扩展情况
            hs = (hs-b)/2    #恢复真正差值
            x,y = convHL( hs, ls )
         
        elif loc in loc_2:  #属于可改变
            hs = (hs-b)+ lsb_2[ loc ]  #恢复真正差值
            x,y = convHL( hs, ls )
                      
        p_ext.append( b )
            
            
        img_data[2*i] = x
        img_data[2*i+1] = y

        global info_a
        info_a.append( [ x , y ,  p[i]] )        
            
    res = img_data.reshape( H,W  )    
 
    cv2.imshow("extract_img" , res )             
    
    
    print("提取的信息:" , p_ext )
    
    return p_ext, res

if __name__ =="__main__":
    loc_1 , loc_2 , lsb_2 , img_emd ,img_src =  embedMsg()    
    p_ext  , ext_img = extractMsg( loc_1 , loc_2 , lsb_2 , img_emd )    
    
    """#比对原始图像和恢复图像,像素值一样,可完美恢复
    H,W = img_src.shape
    for h in range(H):
        for w in range(W):
            if img_src[ h ,w ] != ext_img[ h ,w ]: 
                print("difference pixel!")
    """
        
    cv2.waitKey()        
    cv2.destroyAllWindows()  


四、结果

 可看到可以完好提取和完好恢复

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值