python - 为什么提取出来的水印和嵌入的水印不一样?

标签 python image-processing signal-processing

我正在尝试为大学项目编写这篇论文 paper 的代码。这个想法是在灰度图像中插入一个不可见的水印,以后可以将其提取出来以验证图像的所有权。 这是我为水印嵌入过程编写的代码:

  import pywt
import numpy as np
import  cv2
from PIL import  Image
from math import  sqrt, log10
from scipy.fftpack import dct, idct




def Get_MSB_LSB_Watermark () : #Function that separates the watermark into MSB and LSB images
    MSBs = []
    LSBs = []
    for i in range (len(Watermark)) :
            binary =  '{:0>8}'.format(str(bin(Watermark[i]))[2:])
            MSB = (binary[0:4])
            LSB = (binary[4:])
            MSB = int(MSB, 2)
            LSB = int(LSB,2)
            MSBs.append(MSB)
            LSBs.append(LSB)
    MSBs = np.array(MSBs)
    LSBs = np.array(LSBs)
    return MSBs.reshape(64,64), LSBs.reshape(64,64)



def split(array, nrows, ncols): #Split array into blocks of size nrows* ncols
    r, h = array.shape
    return (array.reshape(h//nrows, nrows, -1, ncols)
                 .swapaxes(1, 2)
                 .reshape(-1, nrows, ncols))


def unblockshaped(arr, h, w): #the inverse of the split function
    n, nrows, ncols = arr.shape
    return (arr.reshape(h//nrows, -1, nrows, ncols)
               .swapaxes(1,2)
               .reshape(h, w))

def ISVD (U,S,V): #the inverse of singular value decomposition
    s = np.zeros(np.shape(U))
    for i in range(4):
        s[i, i] = S[i]
    recon_image = U @ s @ V
    return recon_image

def Watermark_Embedding (blocks, watermark) :
    Watermarked_blocks = []
    k1 = []
    k2 = []
    #convert the watermark to a list
    w = list(np.ndarray.flatten(watermark))
    for i in range (len(blocks)) :
        B = blocks[i]
        #Aplly singular value decoposition to the block
        U, s, V = np.linalg.svd(B)
        #Modify the singular values of the block
        P = s[1] - s[2]
        delta = abs(w[i]) - P
        s[1] = s[1] + delta
        if s[0] >= s[1] :
            k1.append(1)
        else :
            k1.append(-1)
        #the inverse of SVD after watermark embedding
        recunstructed_B = ISVD(U, s, V)
        Watermarked_blocks.append(recunstructed_B)
    for j in range(len(w)):
        if w[j] >= 0:
            k2.append(1)
        else:
            k2.append(-1)
    return k1,k2, np.array(Watermarked_blocks)


def apply_dct(image_array):
    size = image_array[0].__len__()
    all_subdct = np.empty((size, size))
    for i in range (0, size, 4):
        for j in range (0, size, 4):
            subpixels = image_array[i:i+4, j:j+4]
            subdct = dct(dct(subpixels.T, norm="ortho").T, norm="ortho")
            all_subdct[i:i+4, j:j+4] = subdct

    return all_subdct

def inverse_dct(all_subdct):
    size = all_subdct[0].__len__()
    all_subidct = np.empty((size, size))
    for i in range (0, size, 4):
        for j in range (0, size, 4):
            subidct = idct(idct(all_subdct[i:i+4, j:j+4].T, norm="ortho").T, norm="ortho")
            all_subidct[i:i+4, j:j+4] = subidct

    return all_subidct



#read watermark
Watermark = Image.open('Copyright.png').convert('L')
Watermark = list(Watermark.getdata())
#Separate the watermark into LSB and MSB images
Watermark1, Watermark2 = Get_MSB_LSB_Watermark()
#Apply descrete cosine Transform on the two generated images
DCT_Watermark1 = apply_dct(Watermark1)
DCT_Watermark2 = apply_dct(Watermark2)




#read cover Image
Cover_Image = Image.open('10.png').convert('L')
#Apply 1 level descrete wavelet transform
LL1, (LH1, HL1, HH1) = pywt.dwt2(Cover_Image, 'haar')
#Split the LH1 and HL1 subbands into blocks of size 4*4
blocks_LH1 = split(LH1,4,4)
blocks_HL1 = split(HL1,4,4)
#Watermark Embedding in LH1 and HL1 and Keys generation
Key1, Key3, WatermarkedblocksLH1 = Watermark_Embedding(blocks_LH1,DCT_Watermark1)
Key2 ,Key4,  WatermarkedblocksHL1 = Watermark_Embedding(blocks_HL1,DCT_Watermark2)
#Merge the watermzrked Blocks
reconstructed_LH1 = unblockshaped(WatermarkedblocksLH1, 256,256)
reconstructed_HL1 = unblockshaped(WatermarkedblocksHL1, 256,256)
#Apply the inverse of descrete wavelet transform to get the watermarked image
IDWT = pywt.idwt2((LL1, (reconstructed_LH1, reconstructed_HL1, HH1)), 'haar')
cv2.imwrite('Watermarked_img.png', IDWT)

这是我为提取过程编写的代码:

 import pywt
from scipy import fftpack
import numpy as np
import  cv2
from PIL import  Image
import scipy
from math import  sqrt, log10
from Watermark_Embedding import *


def Watermark_Extraction(blocks,key1, key2) :
    Extracted_Watermark = []
    for i in range(len(blocks)):
        B = blocks[i]
        #apply SVD on the Block
        U, s, V = np.linalg.svd(B)
        if key1[i] == 1 :
                P = (s[1] - s[2])
                Extracted_Watermark.append(P)
        else :
                P = (s[0] - s[2])
                Extracted_Watermark.append(P)
    for j in range(len(Extracted_Watermark)) :
        if key2[j] == 1 :
            Extracted_Watermark[j] = Extracted_Watermark[j]
        else :
            Extracted_Watermark[j] = - (Extracted_Watermark[j])
    return np.array(Extracted_Watermark)




def Merge_W1_W2 ():
    Merged_watermark = []
    w1 = list(np.ndarray.flatten(IDCTW1))
    w2 = list(np.ndarray.flatten(IDCTW2))
    for i in range (len(w2)):
        bw1 = '{:0>4}'.format((bin(int(abs(w1[i]))))[2:])
        bw2 = '{:0>4}'.format((bin(int(abs(w2[i]))))[2:])
        P = bw1+bw2
        pixel = (int(P,2))
        Merged_watermark.append(pixel)
    return Merged_watermark






Watermarked_Image = Image.open('Watermarked_img.png')
LL1, (LH1, HL1, HH1) = pywt.dwt2(Watermarked_Image, 'haar')
blocks_LH1 = split(LH1,4,4)
blocks_HL1 = split(HL1,4,4)
W1 = Watermark_Extraction(blocks_LH1, Key1,Key3)
W2 = Watermark_Extraction(blocks_HL1, Key2, Key4)
W1 = W1.reshape(64,64)
W2 = W2.reshape(64,64)

IDCTW1 = inverse_dct(W1)
IDCTW2 = inverse_dct(W2)
Merged = np.array(Merge_W1_W2())
Merged = Merged.reshape(64,64)
cv2.imwrite('Extracted_Watermark.png', Merged)

尺寸为512*512的封面图片:

enter image description here

我用的64*64水印

enter image description here

带水印的图片:

enter image description here

我得到的提取水印:

enter image description here

我使用 SSIM 计算了两个水印之间的相似度:

from skimage.metrics import structural_similarity

 original_Watermark = cv2.imread('Copyright.png')
    extracted_watermark = cv2.imread('Extracted_Watermark.png')
    # Convert images to grayscale
    original_watermark = cv2.cvtColor(original_Watermark, cv2.COLOR_BGR2GRAY)
    extracted_Watermark = cv2.cvtColor(extracted_watermark, cv2.COLOR_BGR2GRAY)
    # Compute SSIM between two images
    (score, diff) = structural_similarity(original_Watermark, extracted_Watermark, full=True)
    print("SSIM = ", score)

我没有对带水印的图像进行任何修改,我得到的 SSIM 是 0.8445354561524052。然而,根据论文,提取的水印的 SSIM 应该是 0.99。 我不知道我的代码有什么问题,两天后我有一个截止日期,所以我真的需要帮助。 提前致谢。

最佳答案

有两个问题:

  1. Merge_W1_W2 中,您使用 intfloat 转换为 int 但这会引入数字错误,其中浮点表示不准确(例如 14.99999999999997);这可以通过使用 round 来修复相反。
  2. 保存 cv2.imwrite('Watermarked_img.png', IDWT) 是有损操作,因为它将 IDWT 中的值四舍五入为最接近的整数;如果您使用 Watermarked_Image = IDWT,那么您将得到完全相同的水印图像。

关于python - 为什么提取出来的水印和嵌入的水印不一样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72698062/

相关文章:

opencv - 在实时 OpenCV 应用程序中去除红外摄像机图像中的太阳光反射

python - 平滑 numpy/pandas 中的一系列加权值

c++ - 如何使用 kissFFT 计算峰值?

python - 从匹配值列表中删除字典

python - Conda 未安装最新版本

python - 如何通过鼠标点击而不是猜测和检查来获取 ROI 边界框坐标

c - 基于英特尔的 DCT 硬件加速?

embedded - 嵌入式软件中的回声消除 (AEC)

Python(OOP)列表附加错误

python - Django Admin、Amazon S3、Heroku——缺少 icon_calendar