DWT-SVD_DWT-DCT-image-watermaking

Embedding of a watermak using DWT-SVD and a DWT-DCT tranform.

Challenge

In my project, I utilized advanced watermarking techniques to embed a mark of size 512x512 into three different images. The primary focus was to ensure the highest possible image quality while effectively embedding the watermark.

To achieve this, I combined cutting-edge watermarking techniques known for their ability to maintain image quality. These techniques involved optimizing the placement and strength of the watermark, considering factors such as perceptual masking and robustness to attacks.

After successfully embedding the watermark in the images, another crucial aspect of the project was to develop an attacking technique. The objective of this technique was to attempt to destroy the embedded mark created by another group while preserving the image’s best possible quality. Striking the right balance between attack effectiveness and its impact on overall image quality was paramount.

Throughout the project, special attention was given to the quality of the images to ensure seamless integration of the watermark without compromising visual appeal or clarity. By employing advanced watermarking techniques and devising an effective attacking strategy, the aim was to demonstrate the robustness and resilience of the embedded mark against potential attacks while maintaining the highest image quality.

Embedding Method Explanation

The watermarking method I employed utilizes two different mark embedding techniques:

  • The first technique involves a two-level wavelet transform in the HL/HL quadrant, where a DCT transform is applied. The most significant bit is selected after sorting the bits, and an 8-bit long code represents a single bit of the mark.

  • The second technique utilizes a three-level wavelet transform in the LL/LL/LL quadrant, applying SVD. In this case, a 2-bit long code corresponds to a single bit of the mark.

This embedding method is designed to simultaneously embed the mark in three different images. A CSV file is utilized for the WPSNR function in the detection method. The detection method takes the original image, the watermarked image, and the image after being attacked as inputs. It determines if the mark is still present in the attacked image and calculates the WPSNR of this image. This method can be easily modified to detect the presence of the mark in any given image.

def mixed_embedding(....):

    #dwt 
    coefficient = pywt.dwt2(original, wavelet='haar')
    quadrants = [coefficient[0],*coefficient[1]]

    coefficient2_dct = pywt.dwt2(quadrants[loc_dct_lv1], wavelet='haar')
    quadrants2_dct = [coefficient2_dct[0],*coefficient2_dct[1]]
    coefficient2_svd = pywt.dwt2(quadrants[loc_svd_lv1], wavelet='haar')
    quadrants2_svd = [coefficient2_svd[0],*coefficient2_svd[1]]

#SVD SU TERZO LIVELLO
    coefficient3_svd = pywt.dwt2(quadrants2_svd[loc_svd_lv1], wavelet='haar')
    quadrants3_svd = [coefficient3_svd[0],*coefficient3_svd[1]

    size = quadrants2_dct[1].shape[0]
    size_svd = quadrants3_svd[1].shape[0]

    #divisione in blocchi dei quadranti scelti
    
    blocks_dct = quadrants2_dct[loc_dct_lv2]
    blocks_dct = np.hsplit(blocks_dct, size//4)
    blocks_svd = quadrants3_svd[loc_svd_lv2]
    blocks_svd = np.hsplit(blocks_svd, size_svd//2)

    for k in range(len(blocks_dct)):
      blocks_dct[k] = np.vsplit(blocks_dct[k], size//4)
      blocks_svd[k] = np.vsplit(blocks_svd[k], size_svd//2)

    # dct, svd; embedding; idct, isvd 

    for i in range(len(blocks_dct)):
      for j in range(len(blocks_dct)):
          blocks_dct[i][j] = dct(dct(blocks_dct[i][j],axis=0, norm='ortho'),axis=1, norm='ortho')           
          U,S,VH = np.linalg.svd(blocks_svd[i][j])
          if(mark[i][j] == 0):  
             blocks_dct[i][j] += alpha_dct*(np.array(padding(blocks_dct[i][j],seq_0_dct)).reshape(4,4))
             S +=  alpha_svd*(np.array(seq_0_svd)) 
          else:
             blocks_dct[i][j] += alpha_dct*(np.array(padding(blocks_dct[i][j],seq_1_dct)).reshape(4,4))
             S +=  alpha_svd*(np.array(seq_1_svd))

          blocks_svd[i][j] = np.dot(U*S,VH)
          blocks_dct[i][j] = idct(idct(blocks_dct[i][j],axis=1, norm='ortho'),axis=0, norm='ortho')
    
    for k in range(len(blocks_dct)):
      blocks_dct[k] = np.array(np.vstack(blocks_dct[k])).reshape(128,4)
      blocks_svd[k] = np.array(np.vstack(blocks_svd[k])).reshape(64,2)
   
    quadrants2_dct[loc_dct_lv2] = np.array(np.hstack(blocks_dct)).reshape(128,128)
    quadrants3_svd[loc_svd_lv2] = np.array(np.hstack(blocks_svd)).reshape(64,64)

    coefficient3_svd = quadrants3_svd[0],(quadrants3_svd[1],quadrants3_svd[2],quadrants3_svd[3])
    quadrants2_svd[loc_svd_lv1] = pywt.idwt2(coefficient3_svd, wavelet='haar')

    coefficient2_dct = quadrants2_dct[0],(quadrants2_dct[1],quadrants2_dct[2],quadrants2_dct[3])
    coefficient2_svd = quadrants2_svd[0],(quadrants2_svd[1],quadrants2_svd[2],quadrants2_svd[3])
    
    #rimettiamo ogni quadrante al suo posto nel primo livello
    quadrants[loc_dct_lv1] = pywt.idwt2(coefficient2_dct, wavelet='haar')
    quadrants[loc_svd_lv1] = pywt.idwt2(coefficient2_svd, wavelet='haar')
    
    coefficient = quadrants[0],(quadrants[1],quadrants[2],quadrants[3])
    final = pywt.idwt2(coefficient, wavelet='haar')

    return np.uint8(np.rint(np.clip(final, 0, 255)))

Attack Method Explanation

The “attacks” file contains various brute-force attacks for destroying the mark on the images:

  • “Base-attacks” is a brute-force method in the spatial domain. It applies different single methods (AWGN, BLUR, SHARPENING, MEDIAN-FILTER, RESIZING, JPEG) to the given image. The best attack from a list of successful attacks is selected, and attempts are made to attack the image again with combined attacks.

  • “Wavelet_attack” follows a similar approach as “Base-attacks.” However, the attack is localized in the area of the DWT transform where the mark seems to be, based on a comparison between the original and watermarked images.

  • “Ftt_attack” and “Dct_attack” work similarly to the other attacks, but they are localized on the most significant bit of the DCT or FTT, where the mark seems to be, after comparing the original and watermarked images.

You can find my full project on the Github Repository, where you can also check the code.