├── Dataset ├── Logo.png ├── Akiyo Video.mp4 ├── Embedded Algorithm.png ├── Watermarked Video.avi └── Watermark_Extracted.png ├── Reference Paper.pdf ├── Codes ├── .vscode │ └── settings.json ├── __pycache__ │ ├── Main.cpython-37.pyc │ ├── Embedding_Algo.cpython-37.pyc │ ├── Embedding_Algo.cpython-38.pyc │ └── Extraction_Algo.cpython-37.pyc ├── Extraction_Algo.py ├── Embedding_Algo.py └── Main.py ├── ML_Video_Watermarking_Project.pptx └── README.md /Dataset/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Dataset/Logo.png -------------------------------------------------------------------------------- /Reference Paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Reference Paper.pdf -------------------------------------------------------------------------------- /Dataset/Akiyo Video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Dataset/Akiyo Video.mp4 -------------------------------------------------------------------------------- /Codes/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.pylintEnabled": true, 3 | "python.linting.enabled": true 4 | } -------------------------------------------------------------------------------- /Dataset/Embedded Algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Dataset/Embedded Algorithm.png -------------------------------------------------------------------------------- /Dataset/Watermarked Video.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Dataset/Watermarked Video.avi -------------------------------------------------------------------------------- /Dataset/Watermark_Extracted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Dataset/Watermark_Extracted.png -------------------------------------------------------------------------------- /ML_Video_Watermarking_Project.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/ML_Video_Watermarking_Project.pptx -------------------------------------------------------------------------------- /Codes/__pycache__/Main.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Codes/__pycache__/Main.cpython-37.pyc -------------------------------------------------------------------------------- /Codes/__pycache__/Embedding_Algo.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Codes/__pycache__/Embedding_Algo.cpython-37.pyc -------------------------------------------------------------------------------- /Codes/__pycache__/Embedding_Algo.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Codes/__pycache__/Embedding_Algo.cpython-38.pyc -------------------------------------------------------------------------------- /Codes/__pycache__/Extraction_Algo.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdas-ghub98/ML_Watermarking/HEAD/Codes/__pycache__/Extraction_Algo.cpython-37.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Robust and Hybrid Video Watermarking using SVD, DWT and Frame Difference 2 | This repository is a partial implementation of the research paper titled 'A Robust Color Video Watermarking Technique Using DWT, SVD and Frame Difference' which has been published in PReM17 Proceedings. The implementation has been done using Python programming language and utilizes the following libraries: 3 | 4 | 10 | 11 | The code is divided into two parts - 12 |
    13 |
  1. Embedding algorithm

    14 | This algorithm adds watermark to the video through the proposed algorithm
  2. 15 |
  3. Extraction algorithm

    16 | This algorithm extracts the watermark image from the video through the proposed algorithm
  4. 17 |
18 | 19 | Dataset folder contains all the paraphernalia for the project. Codes folder contains all the Python implementation codes. 20 | -------------------------------------------------------------------------------- /Codes/Extraction_Algo.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import pywt 3 | from scipy.linalg import svd 4 | from numpy import zeros,dot,uint8 5 | 6 | location = '../Dataset/' 7 | 8 | def FrameCapture(path): 9 | cap = cv2.VideoCapture(path) 10 | count = 0 11 | success = 1 12 | success,image = cap.read() 13 | b,g,r = cv2.split(image) 14 | return r,g,b 15 | 16 | def applyDWT(redframe,greenframe,blueframe): 17 | LLR1,_ = pywt.dwt(redframe,'db1') 18 | LLG1,_ = pywt.dwt(greenframe,'db1') 19 | LLB1,_ = pywt.dwt(blueframe,'db1') 20 | 21 | _,HHR2 = pywt.dwt(LLR1,'db1') 22 | _,HHG2 = pywt.dwt(LLG1,'db1') 23 | _,HHB2 = pywt.dwt(LLB1,'db1') 24 | 25 | print("-------------- 2 rounds of DWT applied and the HH values of each channel returned --------------") 26 | return HHR2,HHG2,HHB2 27 | 28 | def applySVD(mat): 29 | U,S,VT = svd(mat,full_matrices=True) 30 | return U,S,VT 31 | print("-------------- SVD applied on HH sub band successful --------------") 32 | 33 | def applyInverseSVD(u,s,vt): 34 | m,_ = u.shape 35 | n,_ = vt.shape 36 | Sigma = zeros((m,n)) 37 | for i in range(min(m,n)): 38 | Sigma[i,i] = s[i] 39 | B = dot(u,dot(Sigma,vt)) 40 | # print(B.shape) 41 | return B 42 | 43 | def applyIDWT(a,b,c): 44 | temp = pywt.idwt(b,a,'db1') 45 | temp2 = pywt.idwt(temp,c,'db1') 46 | return temp2 47 | 48 | def GetOriginalUSVT(): 49 | src = cv2.imread(location + 'logo.png') 50 | b2,g2,r2 = cv2.split(src) 51 | 52 | LLR3,HHR3 = pywt.dwt(r2,'db1') 53 | LLR4,HHR4 = pywt.dwt(LLR3,'db1') 54 | LLG3,HHG3 = pywt.dwt(g2,'db1') 55 | LLG4,HHG4 = pywt.dwt(LLG3,'db1') 56 | LLB3,HHB3 = pywt.dwt(b2,'db1') 57 | LLB4,HHB4 = pywt.dwt(LLB3,'db1') 58 | 59 | _,sr,vtr = svd(HHR4,full_matrices=True) 60 | _,sg,vtg = svd(HHG4,full_matrices=True) 61 | _,sb,vtb = svd(HHB4,full_matrices=True) 62 | 63 | return sr,vtr,sg,vtg,sb,vtb,LLR3,HHR3,LLG3,HHG3,LLB3,HHB3,LLR4,HHR4,LLG4,HHG4,LLB4,HHB4 64 | def Watermark_Processing(r,g,b,sr,vtr,sg,vtg,sb,vtb,LLR3,HHR3,LLG3,HHG3,LLB3,HHB3,LLR4,HHR4,LLG4,HHG4,LLB4,HHB4): 65 | 66 | r3 = applyInverseSVD(r,sr,vtr) 67 | g3 = applyInverseSVD(g,sg,vtg) 68 | b3 = applyInverseSVD(b,sb,vtb) 69 | 70 | ir = applyIDWT(r3,LLR4,HHR3) 71 | ig = applyIDWT(g3,LLG4,HHG3) 72 | ib = applyIDWT(b3,LLB4,HHB3) 73 | 74 | res = cv2.merge((ib,ig,ir)).astype(uint8) 75 | return res -------------------------------------------------------------------------------- /Codes/Embedding_Algo.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import random 3 | import pywt 4 | from numpy import dot,zeros,array,ndarray,resize,uint8 5 | from scipy.linalg import svd 6 | 7 | location = "../Dataset/" 8 | location2 = "../Dataset/Logo.png" 9 | 10 | # Function to extract frames 11 | def FrameCapture(path): 12 | frames = [] 13 | red_frames =[] 14 | green_frames = [] 15 | blue_frames = [] 16 | cap = cv2.VideoCapture(path) 17 | count = 0 18 | success = 1 19 | while success: 20 | success, image = cap.read() 21 | if success: 22 | frames.append(image) 23 | b,g,r = cv2.split(image) 24 | red_frames.append(r) 25 | green_frames.append(g) 26 | blue_frames.append(b) 27 | count += 1 28 | rf = random.choice(frames) 29 | # cv2.imwrite(location + 'Random Frame.png',rf) 30 | # cv2.imshow('Red Frame',red_frames[0]) 31 | # cv2.waitKey(1000) 32 | # cv2.imshow('Green Frame',green_frames[0]) 33 | # cv2.waitKey(1000) 34 | # cv2.imshow('Blue Frame',blue_frames[0]) 35 | # cv2.waitKey(1000) 36 | # cv2.destroyAllWindows() 37 | print("-------------- Video was split into frames successfully and splitted into RGB frames --------------") 38 | return count,red_frames, green_frames, blue_frames,rf 39 | 40 | #Perfprming frame subtraction by selecting random frame from each channel and subtracting it over all channels 41 | def Frame_Subtract(nof,Red,Green,Blue,rf): 42 | SR = [] 43 | SG = [] 44 | SB = [] 45 | rb,rg,rr = cv2.split(rf) 46 | 47 | for i in range(0,nof,1): 48 | SR.append(cv2.subtract(Red[i],rr)) 49 | SG.append(cv2.subtract(Green[i],rg)) 50 | SB.append(cv2.subtract(Blue[i],rb)) 51 | 52 | # cv2.imshow('Red Subtracted Frame',SR[0]) 53 | # cv2.waitKey(1000) 54 | # cv2.imshow('Green Subtracted Frame',SG[0]) 55 | # cv2.waitKey(1000) 56 | # cv2.imshow('Blue Subtracted Frame',SB[0]) 57 | # cv2.waitKey(1000) 58 | # cv2.destroyAllWindows() 59 | print("-------------- Random frames from each channel were selected and subtracted accordingly --------------") 60 | return SR,SG,SB 61 | 62 | #Function that applies DWT twice on the frames 63 | def ApplyDWT_Frames(rf): 64 | b,g,r = cv2.split(rf) 65 | # cv2.imshow('Random frame',rf) 66 | # cv2.waitKey(1000) 67 | # cv2.imshow('Random red frame',r) 68 | # cv2.waitKey(1000) 69 | # cv2.imshow('Random green frame',g) 70 | # cv2.waitKey(1000) 71 | # cv2.imshow('Random blue frame',b) 72 | # cv2.waitKey(1000) 73 | # cv2.destroyAllWindows() 74 | 75 | # Taking the original matrix and taking the cA(LL) values from DWT 76 | LLR1,HHR1 = pywt.dwt(r,'db1') 77 | LLG1,HHG1 = pywt.dwt(g,'db1') 78 | LLB1,HHB1 = pywt.dwt(b,'db1') 79 | 80 | # cv2.imshow('Red DWT Frame',LLR1) 81 | # cv2.waitKey(4000) 82 | # cv2.imshow('Green DWT Frame',LLG1) 83 | # cv2.waitKey(1000) 84 | # cv2.imshow('Blue DWT Frame',LLB1) 85 | # cv2.waitKey(1000) 86 | # cv2.destroyAllWindows() 87 | # mat = pywt.idwt(LLR1,HHR1,'db1') 88 | 89 | # cv2.imshow('Reconstructed',mat) 90 | # cv2.waitKey(4000) 91 | # cv2.destroyAllWindows() 92 | 93 | #Take the HH sub band and apply DWT again here 94 | LLR2,HHR2 = pywt.dwt(LLR1,'db1') 95 | LLG2,HHG2 = pywt.dwt(LLG1,'db1') 96 | LLB2,HHB2 = pywt.dwt(LLB1,'db1') 97 | 98 | print("-------------- DWT applied twice on frames (once on normal and then on LL sub band.) Returning the HH sub bands --------------") 99 | return LLR1,HHR1,LLR2,HHR2,LLG1,HHG1,LLG2,HHG2,LLB1,HHB1,LLB2,HHB2 100 | 101 | #Applying two rounds of DWT to the logo image 102 | def ApplyDWT_Logo(): 103 | wmk_image = cv2.imread(location2) 104 | gray_wmk = cv2.cvtColor(wmk_image,cv2.COLOR_BGR2GRAY) 105 | LL1,_ = pywt.dwt(gray_wmk,'db1') 106 | _,HH2 = pywt.dwt(LL1,'db1') 107 | 108 | # cv2.imshow('Logo DWTized Frame',HHLogo) 109 | # cv2.waitKey(1000) 110 | # cv2.destroyAllWindows() 111 | print("-------------- DWT applied on Logo --------------") 112 | return HH2 113 | 114 | # Function to apply SVD on the matrice passed as a parameter 115 | def ApplySVD(mat): 116 | U, S, VT = svd(mat, full_matrices=True) 117 | print("-------------- Applying SVD on the HH sub bands successful --------------") 118 | return U,S,VT 119 | 120 | #Function to add the singular matrix S 121 | def Singular_S_Adder(s1,s2): 122 | s3 = s1+s2 123 | # cv2.imshow('Watermarked S matrice',s3) 124 | # cv2.waitKey(1000) 125 | # cv2.destroyAllWindows() 126 | return s3 127 | 128 | #Function to calculate inverse SVD 129 | def InverseSVD(u1,vt1,u2,vt2,s3): 130 | m,_ = u1.shape 131 | n,_ = vt1.shape 132 | #print(u1.shape,'\n\n',vt1.shape,'\n\n',u2.shape,'\n\n',vt2.shape,'\n\n',s3.shape) 133 | Sigma = zeros((m,n)) 134 | for i in range(min(m,n)): 135 | Sigma[i,i] = s3[i] 136 | B = dot(u1,dot(Sigma,vt1)) 137 | # print(B.shape) 138 | return B 139 | 140 | #Function to calculate inverse DWT 141 | def IDWT(a,b,c): 142 | temp = pywt.idwt(b,a,'db1') 143 | # print(temp.shape) 144 | temp2 = pywt.idwt(temp,c, 'db1') 145 | # print(temp2.shape) 146 | return temp2 147 | 148 | #Function to add the watermark on each channel of subtracted frames 149 | def Add_to_Subtracted_Frames(wf,sbrf,sbgf,sbbf,nof): 150 | wmkd_frames = [] 151 | for i in range(0,nof,1): 152 | sub = cv2.merge((sbbf[i],sbgf[i],sbrf[i])) 153 | t = cv2.add(sub,wf) 154 | wmkd_frames.append(t) 155 | return wmkd_frames 156 | 157 | def Create_Video_From_Frames(wmkd_frames): 158 | fps = 30 159 | x,y,z = wmkd_frames[0].shape 160 | size = (y,x) 161 | out = cv2.VideoWriter(location + 'Watermarked Video.avi', cv2.VideoWriter_fourcc(*'DIVX'), fps, size) 162 | for i in range(0,len(wmkd_frames)): 163 | out.write(wmkd_frames[i]) 164 | out.release() 165 | -------------------------------------------------------------------------------- /Codes/Main.py: -------------------------------------------------------------------------------- 1 | import Embedding_Algo as ea 2 | import Extraction_Algo as exa 3 | import numpy as np 4 | import cv2 5 | import timeit 6 | 7 | if __name__ == '__main__': 8 | ########################################################################################################################################## 9 | #EMBEDDING ALGORITHM 10 | 11 | start = timeit.default_timer() 12 | 13 | #Splitting the video frames and then splitting them into RGB frames 14 | nof,R,G,B,rf = ea.FrameCapture(ea.location + "Akiyo Video.mp4") 15 | 16 | #Performing frame subtraction on all the channels and returning them as lists 17 | sbrf,sbgf,sbbf = ea.Frame_Subtract(nof,R,G,B,rf) 18 | 19 | #Applying two rounds of DWT on the random frame 20 | LLR1,HHR1,LLR2,HHR2,LLG1,HHG1,LLG2,HHG2,LLB1,HHB1,LLB2,HHB2 = ea.ApplyDWT_Frames(rf) 21 | 22 | #Applying SVD on the random frame 23 | u1,s1,vt1 = ea.ApplySVD(HHR2) 24 | u2,s2,vt2 = ea.ApplySVD(HHG2) 25 | u3,s3,vt3 = ea.ApplySVD(HHB2) 26 | 27 | # cv2.imshow('Red SVD U Frame',u1) 28 | # cv2.waitKey(1000) 29 | # cv2.imshow('Red S Frame',s1) 30 | # cv2.waitKey(1000) 31 | # cv2.imshow('Red VT Frame',vt1) 32 | # cv2.waitKey(1000) 33 | # cv2.destroyAllWindows() 34 | 35 | # cv2.imshow('Green SVD U Frame',u2) 36 | # cv2.waitKey(1000) 37 | # cv2.imshow('Green S Frame',s2) 38 | # cv2.waitKey(1000) 39 | # cv2.imshow('Blue VT Frame',vt2) 40 | # cv2.waitKey(1000) 41 | # cv2.destroyAllWindows() 42 | 43 | # cv2.imshow('Blue SVD U Frame',u3) 44 | # cv2.waitKey(1000) 45 | # cv2.imshow('Blue S Frame',s3) 46 | # cv2.waitKey(1000) 47 | # cv2.imshow('Blue VT Frame',vt3) 48 | # cv2.waitKey(1000) 49 | # cv2.destroyAllWindows() 50 | 51 | 52 | # Applying DWT once on the splitted logo and acquiring the HH sub band 53 | a2 = ea.ApplyDWT_Logo() 54 | 55 | # Applying SVD once on the HH sub DWT-ized logo 56 | u4,s4,vt4 = ea.ApplySVD(a2) 57 | 58 | # #Now adding the singular matrices 59 | s7 = ea.Singular_S_Adder(s1,s4) 60 | s8 = ea.Singular_S_Adder(s2,s4) 61 | s9 = ea.Singular_S_Adder(s3,s4) 62 | 63 | print("-------------- Singular value of random frame and logo added --------------") 64 | 65 | # Reconstructing three SVD matrixes for R,G and B channels separately 66 | dR = ea.InverseSVD(u1,vt1,u4,vt4,s7) 67 | dG = ea.InverseSVD(u2,vt2,u4,vt4,s8) 68 | dB = ea.InverseSVD(u3,vt3,u4,vt4,s9) 69 | # cv2.imshow('ISVD R frame',dR) 70 | # cv2.waitKey(1000) 71 | # cv2.imshow('ISVD G frame',dG) 72 | # cv2.waitKey(1000) 73 | # cv2.imshow('ISVD B frame',dB) 74 | # cv2.waitKey(1000) 75 | # cv2.destroyAllWindows() 76 | 77 | print("-------------- Inverse SVDs calculcated on the RGB channels --------------") 78 | 79 | # Treat these matrices as HH value and compute the inverse DWT twice on them 80 | eR = ea.IDWT(dR,LLR2,HHR1) 81 | eG = ea.IDWT(dG,LLG2,HHG1) 82 | eB = ea.IDWT(dB,LLB2,HHB1) 83 | 84 | #Merging the watermarked channels after Inverse DWT 85 | f = cv2.merge((eB,eG,eR)).astype(np.uint8) 86 | 87 | cv2.imshow('Reconstructed frame',f) 88 | cv2.waitKey(3000) 89 | cv2.destroyAllWindows() 90 | cv2.imwrite(ea.location + 'Embedded Algorithm.png', f) 91 | 92 | print("-------------- Inverse DWT applied twice on the RGB channels --------------") 93 | 94 | # Adding the watermarked frame to the subtracted frames 95 | watermarked_frames = ea.Add_to_Subtracted_Frames(f,sbrf,sbgf,sbbf,nof) 96 | 97 | print("-------------- Watermarked frames constructed --------------") 98 | 99 | # Creating video using these watermarked frames 100 | ea.Create_Video_From_Frames(watermarked_frames) 101 | 102 | 103 | print("-------------- Watermarked video constructed --------------") 104 | 105 | stop = timeit.default_timer() 106 | 107 | print('Total time taken for embedding algo to work : ',stop-start,'seconds\n\n\n\n\n\n') 108 | 109 | 110 | ########################################################################################################################################## 111 | 112 | 113 | #EXTRACTION ALGORITHM 114 | 115 | start2 = timeit.default_timer() 116 | #Taking the first frame of watermarked video and splitting it into R,G and B channels 117 | rw,gw,bw = exa.FrameCapture(exa.location + 'Watermarked Video.avi') 118 | print("-------------- Taking the first frame from watermarked video and splitting into RGB frames --------------") 119 | # cv2.imshow('Red frame',rw) 120 | # cv2.waitKey(3000) 121 | # cv2.destroyAllWindows() 122 | 123 | #Applying DWT twice on the frame 124 | HHWR,HHWG,HHWB = exa.applyDWT(rw,gw,bw) 125 | # cv2.imshow('HH Red',HHWR) 126 | # cv2.waitKey(3000) 127 | # cv2.destroyAllWindows() 128 | 129 | #Applying SVD on the HH sub band 130 | uwr,swr,vtwr = exa.applySVD(HHWR) 131 | uwg,swg,vtwg = exa.applySVD(HHWG) 132 | uwb,swb,vtwb = exa.applySVD(HHWB) 133 | # cv2.imshow('Red U',uwr) 134 | # cv2.waitKey(3000) 135 | # cv2.destroyAllWindows() 136 | 137 | #Taking the first frame of the non-watermarked video 138 | rnw,bnw,gnw = exa.FrameCapture(exa.location + 'Akiyo Video.mp4') 139 | # cv2.imshow('Red non watermarked',rnw) 140 | # cv2.waitKey(3000) 141 | # cv2.destroyAllWindows() 142 | print("-------------- Taking the first frame of non-watermarked video and splitting into RGB frames --------------") 143 | 144 | #Applying DWT twice on the non-watermarked frame 145 | HHNWR,HHNWG,HHNWB = exa.applyDWT(rnw,gnw,bnw) 146 | # cv2.imshow('Red non watermarked HH',HHNWR) 147 | # cv2.waitKey(3000) 148 | # cv2.destroyAllWindows() 149 | 150 | #Applying SVD on the non-watermarked frame 151 | unwr,snwr,vtnwr = exa.applySVD(HHNWR) 152 | unwg,snwg,vtnwg = exa.applySVD(HHNWG) 153 | unwb,snwb,vtnwb = exa.applySVD(HHNWB) 154 | 155 | #Subtracting the singular values 156 | red_logo = uwr - unwr 157 | green_logo = uwg - unwg 158 | blue_logo = uwb - unwb 159 | 160 | #Get SVD values from original logo file 161 | ur,vtr,ug,vtg,ub,vtb,LLR3,HHR3,LLG3,HHG3,LLB3,HHB3,LLR4,HHR4,LLG4,HHG4,LLB4,HHB4 = exa.GetOriginalUSVT() 162 | 163 | # Reconstructing the watermark 164 | res = exa.Watermark_Processing(red_logo,green_logo,blue_logo,ur,vtr,ug,vtg,ub,vtb,LLR3,HHR3,LLG3,HHG3,LLB3,HHB3,LLR4,HHR4,LLG4,HHG4,LLB4,HHB4) 165 | 166 | cv2.imshow('Extracted Watermark',res) 167 | cv2.waitKey(3000) 168 | cv2.destroyAllWindows() 169 | stop2 = timeit.default_timer() 170 | 171 | #Saving the watermark 172 | cv2.imwrite(exa.location + 'Watermark_Extracted.png', res) 173 | print("-------------- Saving the watermarked image --------------") 174 | 175 | print('Total time taken for extraction algo to work : ',stop2-start2,'seconds\n\n\n\n\n\n') 176 | 177 | ########################################################################################################################################## --------------------------------------------------------------------------------