├── 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 |
5 | - Open CV
6 | - Scipy
7 | - Numpy
8 | - Pywavelet
9 |
10 |
11 | The code is divided into two parts -
12 |
13 | -
Embedding algorithm
14 | This algorithm adds watermark to the video through the proposed algorithm
15 | -
Extraction algorithm
16 | This algorithm extracts the watermark image from the video through the proposed algorithm
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 | ##########################################################################################################################################
--------------------------------------------------------------------------------