├── .gitignore ├── AES-VC ├── main.py ├── shares │ ├── DecryptedImg.png │ ├── P.png │ ├── R.png │ └── cipher.txt └── test.jpg ├── Binary Images ├── BinaryMetrics.py ├── Input.png ├── ModularArithmetic_Implementation.py ├── PixelExpansion_Implementation.py ├── README.md ├── XOR_Implementation.py └── outputs │ ├── MA_Share_1.png │ ├── MA_Share_2.png │ ├── Output_MA.png │ ├── Output_PE(Extraction).png │ ├── Output_PE(Overlap).png │ ├── Output_XOR.png │ ├── PE_SecretShare_1.png │ ├── PE_SecretShare_2.png │ ├── XOR_Share_1.png │ └── XOR_Share_2.png ├── Colour Images ├── ColourMetrics.py ├── HalftoneCMYKDecomposition_Implementation.py ├── Input.png ├── ModularArithmetic_Implementation.py ├── README.md ├── XOR_Implementation.py └── outputs │ ├── CMYK_Share1_1.jpg │ ├── CMYK_Share1_2.jpg │ ├── CMYK_Share1_3.jpg │ ├── CMYK_Share2_1.jpg │ ├── CMYK_Share2_2.jpg │ ├── CMYK_Share2_3.jpg │ ├── CMYK_Share3_1.jpg │ ├── CMYK_Share3_2.jpg │ ├── CMYK_Share3_3.jpg │ ├── MA_Share_1.png │ ├── MA_Share_2.png │ ├── Output_CMYK.jpg │ ├── Output_MA.png │ ├── Output_XOR.png │ ├── XOR_Share_1.png │ └── XOR_Share_2.png ├── Grayscale Images ├── BitLevelDecomposition_Implementation.py ├── GrayscaleMetrics.py ├── Input.png ├── ModularArithmetic_Implementation.py ├── README.md ├── XOR_Implementation.py └── outputs │ ├── BLD_SecretShare_1.png │ ├── BLD_SecretShare_2.png │ ├── MA_Share_1.png │ ├── MA_Share_2.png │ ├── Output_BLD(Extraction).png │ ├── Output_BLD(Overlap).png │ ├── Output_MA.png │ ├── Output_XOR.png │ ├── XOR_Share_1.png │ └── XOR_Share_2.png ├── README.md ├── Report.pdf ├── Screenshots ├── Binary Images │ ├── Modular Arithmetic Implementation.png │ ├── Pixel Expansion Implementation.png │ └── XOR Implementation.png ├── Colour Images │ ├── Modular Arithmetic Implementation.png │ └── XOR Implementation.png └── Grayscale Images │ ├── Bit Level Decomposition Implementation.png │ ├── Modular Arithmetic Implementation.png │ └── XOR Implementation.png ├── requirements.txt └── utils ├── ncorr.py └── psnr.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /AES-VC/main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """VC-WithKey.ipynb 3 | 4 | Automatically generated by Colaboratory. 5 | 6 | Original file is located at 7 | https://colab.research.google.com/drive/1H-LAXTcnBvVJATtcyCl8_g1hdAG0xZeS 8 | """ 9 | 10 | import base64 11 | from PIL import Image 12 | with open("test.jpg", "rb") as img_file: 13 | BI = base64.b64encode(img_file.read()) 14 | 15 | BI = BI.decode("utf-8") 16 | 17 | import hashlib 18 | # My key 19 | K = "Hello, World. ThisIsMyKey." 20 | 21 | SK = hashlib.sha256(K.encode()) 22 | 23 | print("The hexadecimal equivalent of SHA256 is : ") 24 | print(SK.hexdigest()) 25 | 26 | 27 | 28 | # AES 256 in OFB mode: 29 | from Crypto.Cipher import AES 30 | from Crypto.Random import new as Random 31 | from hashlib import sha256 32 | from base64 import b64encode,b64decode 33 | 34 | class AESCipher: 35 | def __init__(self,data,key): 36 | self.block_size = 16 37 | self.data = data 38 | self.key = sha256(key.encode()).digest()[:32] 39 | self.pad = lambda s: s + (self.block_size - len(s) % self.block_size) * chr (self.block_size - len(s) % self.block_size) 40 | self.unpad = lambda s: s[:-ord(s[len(s) - 1:])] 41 | 42 | def encrypt(self): 43 | plain_text = self.pad(self.data) 44 | iv = Random().read(AES.block_size) 45 | cipher = AES.new(self.key,AES.MODE_OFB,iv) 46 | return b64encode(iv + cipher.encrypt(plain_text.encode())).decode() 47 | 48 | # Encrypting image using base 64 encoded text and hashed key - SHA256 49 | # AES-256 50 | c = AESCipher(BI,SK.hexdigest()).encrypt() 51 | # print(c) 52 | #print(len(c)) 53 | 54 | """Additional Encryption""" 55 | 56 | import numpy as np 57 | import cv2 58 | w = 255 59 | h = len(K) 60 | # creating new Image C of size(w,h) 61 | # initializing as blank 62 | C = np.ones((h,w,1), dtype = 'uint8') 63 | 64 | # Filling pixels in C 65 | for i in range(h): 66 | j = ord(K[i]) 67 | for k in range(w): 68 | if k < j: 69 | C[i][k][0] = 0 70 | else: 71 | break 72 | 73 | # print(C[0]) 74 | 75 | # Dividing C into R and P 76 | # initializing R and P of same size as C 77 | R = np.ones((h,w,3), dtype = 'uint8') 78 | P = np.ones((h,w,3), dtype = 'uint8') 79 | 80 | for i in range(h): 81 | for j in range(w): 82 | r = np.random.normal(0,1,1) 83 | #print("r: ", r) 84 | R[i][j][0] = r 85 | 86 | for i in range(h): 87 | for j in range(w): 88 | p = R[i][j][0] ^ C[i][j][0] 89 | P[i][j][0] = p 90 | 91 | # print(np.unique(R[:, :, 0])) 92 | 93 | import matplotlib.pyplot as plt 94 | plt.imshow(P) 95 | plt.show() 96 | 97 | plt.imshow(R) 98 | plt.show() 99 | 100 | filename = 'shares/R.png' 101 | cv2.imwrite(filename, R) 102 | 103 | filename = 'shares/P.png' 104 | cv2.imwrite(filename, P) 105 | 106 | """Encrypt CipherText further""" 107 | 108 | import pandas as pd 109 | 110 | xdf = pd.DataFrame(columns = ['1','2']) 111 | a = [] 112 | b = [] 113 | cnt = 0 114 | for i in P: 115 | #print("I: ", i) 116 | #print("I Shape: ", i.shape) 117 | cnt+=1 118 | k = 0 119 | n1 = [] 120 | n2 = [] 121 | for j in i: 122 | #print("J SHape: ", j.shape) 123 | if k%2==0: 124 | n1.append(np.sum(j)) 125 | else: 126 | n2.append(np.sum(j)) 127 | k += 1 128 | a.append(sum(n1)) 129 | b.append(sum(n2)) 130 | # print("Cnt: ", cnt) 131 | xdf['1'] = a 132 | xdf['2'] = b 133 | 134 | ydf = pd.DataFrame(columns = ['1','2']) 135 | a = [] 136 | b = [] 137 | for i in R: 138 | k = 0 139 | n1 = [] 140 | n2 = [] 141 | for j in i: 142 | if k%2==0: 143 | n1.append(np.sum(j)) 144 | else: 145 | n2.append(np.sum(j)) 146 | k += 1 147 | a.append(sum(n1)) 148 | b.append(sum(n2)) 149 | ydf['1'] = a 150 | ydf['2'] = b 151 | 152 | print(xdf) 153 | 154 | print(ydf) 155 | 156 | """Fit LR Model 157 | 158 | """ 159 | 160 | from sklearn.linear_model import LinearRegression 161 | LRmodel = LinearRegression() 162 | LRmodel.fit(xdf,ydf) 163 | 164 | zdf = pd.DataFrame(columns = ['1','2']) 165 | a = [] 166 | b = [] 167 | for i in C: 168 | k = 0 169 | n1 = [] 170 | n2 = [] 171 | for j in i: 172 | if k%2==0: 173 | n1.append(np.sum(j)) 174 | else: 175 | n2.append(np.sum(j)) 176 | k += 1 177 | a.append(sum(n1)) 178 | b.append(sum(n2)) 179 | zdf['1'] = a 180 | zdf['2'] = b 181 | 182 | zdf 183 | 184 | predict = LRmodel.predict([[sum(zdf['1']),sum(zdf['2'])]]) 185 | 186 | print(predict) 187 | 188 | x = round(predict[0][0])%26 189 | y = round(predict[0][1])%26 190 | 191 | txt = [] 192 | for each in c: 193 | ch = ord(each) + x - y 194 | txt.append(int(ch)) 195 | 196 | len(txt) 197 | 198 | text = "" 199 | for t in txt: 200 | text += chr(t) + " " 201 | 202 | text 203 | 204 | f = open("shares/cipher.txt",'a',encoding='utf-8') 205 | f.write(text) 206 | f.close() 207 | 208 | """# Decryption""" 209 | 210 | cipher = text 211 | 212 | P = cv2.imread('shares/P.png') 213 | R = cv2.imread('shares/R.png') 214 | 215 | h = np.shape(P)[0] 216 | w = np.shape(P)[1] 217 | 218 | CK = np.ones((h,w,1), dtype = 'uint8') 219 | 220 | for i in range(h): 221 | for j in range(w): 222 | ck = P[i][j][0] ^ R[i][j][0] 223 | CK[i][j][0] = ck 224 | 225 | K1 = [] 226 | for i in range(len(CK)): 227 | K1.append(0) 228 | 229 | for i in range(len(CK)): 230 | count = 0 231 | for j in range(len(CK[i])): 232 | if CK[i][j][0] == 0: 233 | count += 1 234 | K1[i] = chr(count) 235 | 236 | K1 = "".join(K1) 237 | 238 | K1 239 | 240 | SK1 = hashlib.sha256(K1.encode()) 241 | 242 | print("The hexadecimal equivalent of SHA256 is : ") 243 | print(SK1.hexdigest()) 244 | 245 | from Crypto.Cipher import AES 246 | from Crypto.Random import new as Random 247 | from hashlib import sha256 248 | from base64 import b64encode,b64decode 249 | 250 | class AESCipher: 251 | def __init__(self,data,key): 252 | self.block_size = 16 253 | self.data = data 254 | self.key = sha256(key.encode()).digest()[:32] 255 | self.pad = lambda s: s + (self.block_size - len(s) % self.block_size) * chr (self.block_size - len(s) % self.block_size) 256 | self.unpad = lambda s: s[:-ord(s[len(s) - 1:])] 257 | 258 | def decrypt(self): 259 | cipher_text = b64decode(self.data.encode()) 260 | iv = cipher_text[:self.block_size] 261 | cipher = AES.new(self.key,AES.MODE_OFB,iv) 262 | return self.unpad(cipher.decrypt(cipher_text[self.block_size:])).decode() 263 | 264 | xdf = pd.DataFrame(columns = ['1','2']) 265 | a = [] 266 | b = [] 267 | for i in P: 268 | k = 0 269 | n1 = [] 270 | n2 = [] 271 | for j in i: 272 | if k%2==0: 273 | n1.append(np.sum(j)) 274 | else: 275 | n2.append(np.sum(j)) 276 | k += 1 277 | a.append(sum(n1)) 278 | b.append(sum(n2)) 279 | xdf['1'] = a 280 | xdf['2'] = b 281 | 282 | ydf = pd.DataFrame(columns = ['1','2']) 283 | a = [] 284 | b = [] 285 | for i in R: 286 | k = 0 287 | n1 = [] 288 | n2 = [] 289 | for j in i: 290 | if k%2==0: 291 | n1.append(np.sum(j)) 292 | else: 293 | n2.append(np.sum(j)) 294 | k += 1 295 | a.append(sum(n1)) 296 | b.append(sum(n2)) 297 | ydf['1'] = a 298 | ydf['2'] = b 299 | 300 | LRmodel = LinearRegression() 301 | LRmodel.fit(xdf,ydf) 302 | 303 | zdf = pd.DataFrame(columns = ['1','2']) 304 | a = [] 305 | b = [] 306 | for i in CK: 307 | k = 0 308 | n1 = [] 309 | n2 = [] 310 | for j in i: 311 | if k%2==0: 312 | n1.append(np.sum(j)) 313 | else: 314 | n2.append(np.sum(j)) 315 | k += 1 316 | a.append(sum(n1)) 317 | b.append(sum(n2)) 318 | zdf['1'] = a 319 | zdf['2'] = b 320 | 321 | predict = LRmodel.predict([[sum(zdf['1']),sum(zdf['2'])]]) 322 | 323 | x = round(predict[0][0])%26 324 | y = round(predict[0][1])%26 325 | 326 | cipher = cipher.split(' ') 327 | 328 | txt = [] 329 | for each in cipher: 330 | try: 331 | ch = ord(each) - x + y 332 | txt.append(int(ch)) 333 | except: 334 | print(each) 335 | 336 | text = "" 337 | for t in txt: 338 | text += chr(t) 339 | 340 | de = AESCipher(text,SK1.hexdigest()).decrypt() 341 | 342 | print(len(text)) 343 | 344 | print(len(SK1.hexdigest())) 345 | 346 | de = de.encode("utf-8") 347 | 348 | with open("shares/DecryptedImg.png", "wb") as fh: 349 | fh.write(base64.decodebytes(de)) 350 | 351 | print("Image is saved 'DecryptedImg.png' ...") 352 | -------------------------------------------------------------------------------- /AES-VC/shares/DecryptedImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/AES-VC/shares/DecryptedImg.png -------------------------------------------------------------------------------- /AES-VC/shares/P.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/AES-VC/shares/P.png -------------------------------------------------------------------------------- /AES-VC/shares/R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/AES-VC/shares/R.png -------------------------------------------------------------------------------- /AES-VC/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/AES-VC/test.jpg -------------------------------------------------------------------------------- /Binary Images/BinaryMetrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | from scipy import signal 4 | from PIL import Image 5 | 6 | def normxcorr2D(image, template): 7 | """ 8 | Normalized cross-correlation for 2D PIL images 9 | Adapted from: https://github.com/JustinLiang/ComputerVisionProjects/ 10 | Inputs: 11 | ---------------- 12 | template The template. A PIL image. Elements cannot all be equal. 13 | image The PIL image. 14 | Output: 15 | ---------------- 16 | nxcorr Array of cross-correlation coefficients, in the range 17 | -1.0 to 1.0. Size == Input image and template shape 18 | Wherever the search space has zero variance under the template, 19 | normalized cross-correlation is undefined. 20 | """ 21 | 22 | # (one-time) normalization of template 23 | t = np.asarray(template, dtype=np.float64) 24 | t = t - np.mean(t) 25 | norm = math.sqrt(np.sum(np.square(t))) 26 | if norm == 0: 27 | raise ValueError("Norm of the input is 0") 28 | t = t / norm 29 | 30 | # create filter to sum values under template 31 | sum_filter = np.ones(np.shape(t)) 32 | 33 | # get image 34 | a = np.asarray(image, dtype=np.float64) 35 | #also want squared values 36 | aa = np.square(a) 37 | 38 | # compute sums of values and sums of values squared under template 39 | a_sum = signal.correlate(a, sum_filter, 'same') 40 | aa_sum = signal.correlate(aa, sum_filter, 'same') 41 | # Note: The above two lines could be made more efficient by 42 | # exploiting the fact that sum_filter is separable. 43 | # Even better would be to take advantage of integral images 44 | 45 | # compute correlation, 't' is normalized, 'a' is not (yet) 46 | numer = signal.correlate(a, t, 'same') 47 | # (each time) normalization of the window under the template 48 | denom = np.sqrt(aa_sum - np.square(a_sum)/np.size(t)) 49 | 50 | # wherever the denominator is near zero, this must be because the image 51 | # window is near constant (and therefore the normalized cross correlation 52 | # is undefined). Set nxcorr to zero in these regions 53 | tol = np.sqrt(np.finfo(denom.dtype).eps) 54 | nxcorr = np.where(denom < tol, 0, numer/denom) 55 | 56 | # if any of the coefficients are outside the range [-1 1], they will be 57 | # unstable to small variance in a or t, so set them to zero to reflect 58 | # the undefined 0/0 condition 59 | nxcorr = np.where(np.abs(nxcorr-1.) > np.sqrt(np.finfo(nxcorr.dtype).eps),nxcorr,0) 60 | 61 | return np.mean(nxcorr) 62 | 63 | 64 | def psnr(original, contrast): 65 | mse = np.mean((original - contrast) ** 2) 66 | if mse == 0: 67 | return 100 68 | PIXEL_MAX = 255.0 69 | PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) 70 | return PSNR -------------------------------------------------------------------------------- /Binary Images/Input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/Input.png -------------------------------------------------------------------------------- /Binary Images/ModularArithmetic_Implementation.py: -------------------------------------------------------------------------------- 1 | # Modular Arithmetic implementation for Binary Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from BinaryMetrics import psnr, normxcorr2D 6 | 7 | def encrypt(input_image, share_size): 8 | image = np.asarray(input_image).astype(np.uint8) 9 | (row, column) = image.shape 10 | shares = np.random.randint(0, 2, size=(row, column, share_size)) 11 | shares[:,:,-1] = image.copy() 12 | for i in range(share_size-1): 13 | shares[:,:,-1] = (shares[:,:,-1] + shares[:,:,i])%2 14 | 15 | 16 | return shares, image 17 | 18 | def decrypt(shares): 19 | (row, column, share_size) = shares.shape 20 | shares_image = shares.copy() 21 | for i in range(share_size-1): 22 | shares_image[:,:,-1] = (shares_image[:,:,-1] - shares_image[:,:,i] + 2)%2 23 | 24 | final_output = shares_image[:,:,share_size-1] 25 | output_image = Image.fromarray(final_output.astype(np.uint8) * 255) 26 | return output_image, final_output 27 | 28 | 29 | if __name__ == "__main__": 30 | 31 | print("Save input image as 'Input.png' in the same folder as this file\n") 32 | 33 | try: 34 | share_size = int(input("Input the number of shares images you want to create for encrypting (min is 2, max is 8) : ")) 35 | if share_size < 2 or share_size > 8: 36 | raise ValueError 37 | except ValueError: 38 | print("Input is not a valid integer!") 39 | exit(0) 40 | 41 | 42 | try: 43 | input_image = Image.open('Input.png').convert('1') 44 | 45 | except FileNotFoundError: 46 | print("Input file not found!") 47 | exit(0) 48 | 49 | print("Image uploaded successfully!") 50 | print("Input image size (in pixels) : ", input_image.size) 51 | print("Number of shares image = ", share_size) 52 | 53 | shares, input_matrix = encrypt(input_image, share_size) 54 | 55 | for ind in range(share_size): 56 | image = Image.fromarray(shares[:,:,ind].astype(np.uint8) * 255) 57 | name = "outputs/MA_Share_" + str(ind+1) + ".png" 58 | image.save(name) 59 | 60 | output_image, output_matrix = decrypt(shares) 61 | output_image.save('outputs/Output_MA.png', mode = '1') 62 | print("Image is saved 'Output_MA.png' ...") 63 | 64 | print("Evaluation metrics : ") 65 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 66 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Binary Images/PixelExpansion_Implementation.py: -------------------------------------------------------------------------------- 1 | # Pixel Expansion implementation for Binary Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from BinaryMetrics import psnr, normxcorr2D 6 | 7 | def extract_colour(): 8 | colour = [[0,0,1,1], [1,1,0,0], [1,0,0,1],[0,1,1,0],[1,0,1,0],[0,1,0,1]] 9 | return np.array(colour[np.random.randint(0,6)]) 10 | 11 | 12 | def encrypt(input_image): 13 | input_matrix = np.asarray(input_image).astype(np.uint8) 14 | 15 | (row, column) = input_matrix.shape 16 | secret_share1 = np.empty((2*row, 2*column)).astype('uint8') 17 | secret_share2 = np.empty((2*row, 2*column)).astype('uint8') 18 | 19 | for i in range(row): 20 | for j in range(column): 21 | colour = extract_colour() 22 | secret_share1[2*i][2*j] = secret_share2[2*i][2*j] = colour[0] 23 | secret_share1[2*i + 1][2*j] = secret_share2[2*i + 1][2*j] = colour[1] 24 | secret_share1[2*i][2*j + 1] = secret_share2[2*i][2*j + 1] = colour[2] 25 | secret_share1[2*i + 1][2*j + 1] = secret_share2[2*i + 1][2*j + 1] = colour[3] 26 | 27 | if input_matrix[i][j] == 0: 28 | secret_share2[2*i][2*j] = 1 - secret_share2[2*i][2*j] 29 | secret_share2[2*i + 1][2*j] = 1 - secret_share2[2*i + 1][2*j] 30 | secret_share2[2*i][2*j + 1] = 1 - secret_share2[2*i][2*j + 1] 31 | secret_share2[2*i + 1][2*j + 1] = 1 - secret_share2[2*i + 1][2*j + 1] 32 | 33 | return secret_share1, secret_share2, input_matrix 34 | 35 | 36 | def decrypt(secret_share1, secret_share2): 37 | ''' 38 | Black -> 0 39 | White -> 1 40 | 41 | White + White -> White ( 1 + 1 -> 1) 42 | White + Black -> Black ( 1 + 0 -> 0) 43 | Black + White -> Black ( 0 + 1 -> 0) 44 | Black + Black -> Black ( 0 + 0 -> 0) 45 | 46 | Best operator to use for this is - bitwise and 47 | 48 | ''' 49 | overlap_matrix = secret_share1 & secret_share2 50 | (row, column) = secret_share1.shape 51 | row = int(row/2) 52 | column = int(column/2) 53 | extraction_matrix = np.ones((row, column)) 54 | 55 | for i in range(row): 56 | for j in range(column): 57 | cnt = overlap_matrix[2*i][2*j] + overlap_matrix[2*i + 1][2*j] + overlap_matrix[2*i][2*j + 1] + overlap_matrix[2*i + 1][2*j + 1] 58 | if cnt == 0: 59 | extraction_matrix[i][j] = 0 60 | 61 | return overlap_matrix, extraction_matrix 62 | 63 | if __name__ == "__main__": 64 | 65 | print("Save input image as 'Input.png' in the same folder as this file\n") 66 | 67 | try: 68 | input_image = Image.open('Input.png').convert('1') 69 | 70 | except FileNotFoundError: 71 | print("Input file not found!") 72 | exit(0) 73 | 74 | print("Image uploaded successfully!") 75 | print("Input image size (in pixels) : ", input_image.size) 76 | print("Number of shares image = 2") 77 | 78 | secret_share1, secret_share2, input_matrix = encrypt(input_image) 79 | 80 | image1 = Image.fromarray(secret_share1.astype(np.uint8) * 255) 81 | image1.save("outputs/PE_SecretShare_1.png") 82 | image2 = Image.fromarray(secret_share2.astype(np.uint8) * 255) 83 | image2.save("outputs/PE_SecretShare_2.png") 84 | 85 | overlap_matrix, extraction_matrix = decrypt(secret_share1, secret_share2) 86 | extraction_output = Image.fromarray(extraction_matrix.astype(np.uint8) * 255) 87 | overlap_output = Image.fromarray(overlap_matrix.astype(np.uint8) * 255) 88 | 89 | extraction_output.save('outputs/Output_PE(Extraction).png', mode = '1') 90 | print("Image is saved 'Output_PE(Extraction).png' ...") 91 | 92 | overlap_output = overlap_output.resize(input_image.size) 93 | overlap_matrix = np.asarray(overlap_output).astype(np.uint8) 94 | overlap_output.save('outputs/Output_PE(Overlap).png', mode = '1') 95 | print("Image is saved 'outputs/Output_PE(Overlap).png' ...\n\n") 96 | 97 | print("Evaluation metrics for Extraction algorithm: ") 98 | print(f"PSNR value is {psnr(input_matrix, extraction_matrix)} dB") 99 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, extraction_matrix)}") 100 | 101 | print("\n\nEvaluation metrics for Overlap algorithm: ") 102 | print(f"PSNR value is {psnr(input_matrix, overlap_matrix)} dB") 103 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, overlap_matrix)}") 104 | 105 | -------------------------------------------------------------------------------- /Binary Images/README.md: -------------------------------------------------------------------------------- 1 | # Visual Cryptography for Binary images -------------------------------------------------------------------------------- /Binary Images/XOR_Implementation.py: -------------------------------------------------------------------------------- 1 | # XOR implementation for Binary Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from BinaryMetrics import psnr, normxcorr2D 6 | 7 | def encrypt(input_image, share_size): 8 | image = np.asarray(input_image) 9 | (row, column) = image.shape 10 | shares = np.random.randint(0, 2, size=(row, column, share_size))*255 11 | shares[:,:,-1] = image.copy() 12 | for i in range(share_size-1): 13 | shares[:,:,-1] = shares[:,:,-1] ^ shares[:,:,i] 14 | 15 | return shares, image 16 | 17 | def decrypt(shares): 18 | (row, column, share_size) = shares.shape 19 | shares_image = shares.copy() 20 | for i in range(share_size-1): 21 | shares_image[:,:,-1] = shares_image[:,:,-1] ^ shares_image[:,:,i] 22 | 23 | final_output = shares_image[:,:,share_size-1] 24 | output_image = Image.fromarray(final_output.astype(np.uint8)) 25 | return output_image, final_output 26 | 27 | 28 | if __name__ == "__main__": 29 | 30 | print("Save input image as 'Input.png' in the same folder as this file\n") 31 | 32 | try: 33 | share_size = int(input("Input the number of shares images you want to create for encrypting (min is 2, max is 8) : ")) 34 | if share_size < 2 or share_size > 8: 35 | raise ValueError 36 | except ValueError: 37 | print("Input is not a valid integer!") 38 | exit(0) 39 | 40 | 41 | try: 42 | input_image = Image.open('Input.png').convert('L') 43 | 44 | except FileNotFoundError: 45 | print("Input file not found!") 46 | exit(0) 47 | 48 | print("Image uploaded successfully!") 49 | print("Input image size (in pixels) : ", input_image.size) 50 | print("Number of shares image = ", share_size) 51 | 52 | shares, input_matrix = encrypt(input_image, share_size) 53 | 54 | for ind in range(share_size): 55 | image = Image.fromarray(shares[:,:,ind].astype(np.uint8)) 56 | name = "outputs/XOR_Share_" + str(ind+1) + ".png" 57 | image.save(name) 58 | 59 | output_image, output_matrix = decrypt(shares) 60 | 61 | output_image.save('outputs/Output_XOR.png') 62 | print("Image is saved 'Output_XOR.png' ...") 63 | 64 | print("Evaluation metrics : ") 65 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 66 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Binary Images/outputs/MA_Share_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/MA_Share_1.png -------------------------------------------------------------------------------- /Binary Images/outputs/MA_Share_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/MA_Share_2.png -------------------------------------------------------------------------------- /Binary Images/outputs/Output_MA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/Output_MA.png -------------------------------------------------------------------------------- /Binary Images/outputs/Output_PE(Extraction).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/Output_PE(Extraction).png -------------------------------------------------------------------------------- /Binary Images/outputs/Output_PE(Overlap).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/Output_PE(Overlap).png -------------------------------------------------------------------------------- /Binary Images/outputs/Output_XOR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/Output_XOR.png -------------------------------------------------------------------------------- /Binary Images/outputs/PE_SecretShare_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/PE_SecretShare_1.png -------------------------------------------------------------------------------- /Binary Images/outputs/PE_SecretShare_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/PE_SecretShare_2.png -------------------------------------------------------------------------------- /Binary Images/outputs/XOR_Share_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/XOR_Share_1.png -------------------------------------------------------------------------------- /Binary Images/outputs/XOR_Share_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Binary Images/outputs/XOR_Share_2.png -------------------------------------------------------------------------------- /Colour Images/ColourMetrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | from scipy import signal 4 | from PIL import Image 5 | 6 | def normxcorr2D(image, template): 7 | """ 8 | Normalized cross-correlation for 2D PIL images 9 | Adapted from: https://github.com/JustinLiang/ComputerVisionProjects/ 10 | Inputs: 11 | ---------------- 12 | template The template. A PIL image. Elements cannot all be equal. 13 | image The PIL image. 14 | Output: 15 | ---------------- 16 | nxcorr Array of cross-correlation coefficients, in the range 17 | -1.0 to 1.0. Size == Input image and template shape 18 | Wherever the search space has zero variance under the template, 19 | normalized cross-correlation is undefined. 20 | """ 21 | 22 | # (one-time) normalization of template 23 | t = np.asarray(template, dtype=np.float64) 24 | t = t - np.mean(t) 25 | norm = math.sqrt(np.sum(np.square(t))) 26 | if norm == 0: 27 | raise ValueError("Norm of the input is 0") 28 | t = t / norm 29 | 30 | # create filter to sum values under template 31 | sum_filter = np.ones(np.shape(t)) 32 | 33 | # get image 34 | a = np.asarray(image, dtype=np.float64) 35 | #also want squared values 36 | aa = np.square(a) 37 | 38 | # compute sums of values and sums of values squared under template 39 | a_sum = signal.correlate(a, sum_filter, 'same') 40 | aa_sum = signal.correlate(aa, sum_filter, 'same') 41 | # Note: The above two lines could be made more efficient by 42 | # exploiting the fact that sum_filter is separable. 43 | # Even better would be to take advantage of integral images 44 | 45 | # compute correlation, 't' is normalized, 'a' is not (yet) 46 | numer = signal.correlate(a, t, 'same') 47 | # (each time) normalization of the window under the template 48 | denom = np.sqrt(aa_sum - np.square(a_sum)/np.size(t)) 49 | 50 | # wherever the denominator is near zero, this must be because the image 51 | # window is near constant (and therefore the normalized cross correlation 52 | # is undefined). Set nxcorr to zero in these regions 53 | tol = np.sqrt(np.finfo(denom.dtype).eps) 54 | nxcorr = np.where(denom < tol, 0, numer/denom) 55 | 56 | # if any of the coefficients are outside the range [-1 1], they will be 57 | # unstable to small variance in a or t, so set them to zero to reflect 58 | # the undefined 0/0 condition 59 | nxcorr = np.where(np.abs(nxcorr-1.) > np.sqrt(np.finfo(nxcorr.dtype).eps),nxcorr,0) 60 | 61 | return np.mean(nxcorr) 62 | 63 | 64 | def psnr(original, contrast): 65 | mse = np.mean((original - contrast) ** 2) 66 | if mse == 0: 67 | return 100 68 | PIXEL_MAX = 255.0 69 | PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) 70 | return PSNR -------------------------------------------------------------------------------- /Colour Images/HalftoneCMYKDecomposition_Implementation.py: -------------------------------------------------------------------------------- 1 | # Halftone CMYK Decomposition for Colour Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from ColourMetrics import psnr, normxcorr2D 6 | import cv2 7 | def CMYK_Decomposition(input_image): 8 | input_matrix = np.asarray(input_image) 9 | 10 | color_image = input_image.convert('CMYK') 11 | bw_image = input_image.convert('1') 12 | outfile1 = Image.new("CMYK", [dimension for dimension in input_image.size]) 13 | outfile2 = Image.new("CMYK", [dimension for dimension in input_image.size]) 14 | outfile3 = Image.new("CMYK", [dimension for dimension in input_image.size]) 15 | 16 | 17 | for x in range(0, input_image.size[0], 1): 18 | for y in range(0, input_image.size[1], 1): 19 | sourcepixel = input_image.getpixel((x, y)) 20 | outfile1.putpixel((x, y),(sourcepixel[0],0,0,0)) 21 | outfile2.putpixel((x, y),(0,sourcepixel[1],0,0)) 22 | outfile3.putpixel((x, y),(0,0,sourcepixel[2],0)) 23 | 24 | outfile1.save('outputs/CMYK_Share1_1.jpg') 25 | outfile2.save('outputs/CMYK_Share1_2.jpg') 26 | outfile3.save('outputs/CMYK_Share1_3.jpg') 27 | 28 | print("CMYK Decomposition Done!") 29 | 30 | return input_matrix 31 | 32 | 33 | def halftoneConversion(): 34 | image1 = Image.open("outputs/CMYK_Share1_1.jpg").convert('1') 35 | image2 = Image.open("outputs/CMYK_Share1_2.jpg").convert('1') 36 | image3 = Image.open("outputs/CMYK_Share1_3.jpg").convert('1') 37 | 38 | hf1 = Image.new("CMYK", [dimension for dimension in image1.size]) 39 | hf2 = Image.new("CMYK", [dimension for dimension in image1.size]) 40 | hf3 = Image.new("CMYK", [dimension for dimension in image1.size]) 41 | 42 | for x in range(0, image1.size[0]): 43 | for y in range(0, image1.size[1]): 44 | pixel_color1 = image1.getpixel((x, y)) 45 | pixel_color2 = image2.getpixel((x, y)) 46 | pixel_color3 = image3.getpixel((x, y)) 47 | if pixel_color1 == 255: 48 | hf1.putpixel((x, y),(255,0,0,0)) 49 | else: 50 | hf1.putpixel((x, y),(0,0,0,0)) 51 | 52 | if pixel_color2 == 255: 53 | hf2.putpixel((x, y),(0,255,0,0)) 54 | else: 55 | hf2.putpixel((x, y),(0,0,0,0)) 56 | 57 | if pixel_color3 == 255: 58 | hf3.putpixel((x, y),(0,0,255,0)) 59 | else: 60 | hf3.putpixel((x, y),(0,0,0,0)) 61 | 62 | hf1.save('outputs/CMYK_Share2_1.jpg') 63 | hf2.save('outputs/CMYK_Share2_2.jpg') 64 | hf3.save('outputs/CMYK_Share2_3.jpg') 65 | 66 | print("Halftone Conversion Done!") 67 | 68 | def generateShares(): 69 | image1 = Image.open('outputs/CMYK_Share2_1.jpg').convert('CMYK') 70 | image2 = Image.open('outputs/CMYK_Share2_2.jpg').convert('CMYK') 71 | image3 = Image.open('outputs/CMYK_Share2_3.jpg').convert('CMYK') 72 | 73 | share1 = Image.new("CMYK", [dimension * 2 for dimension in image1.size]) 74 | share2 = Image.new("CMYK", [dimension * 2 for dimension in image2.size]) 75 | share3 = Image.new("CMYK", [dimension * 2 for dimension in image3.size]) 76 | 77 | for x in range(0, image1.size[0]): 78 | for y in range(0, image1.size[1]): 79 | pixelcolor = image1.getpixel((x, y)) 80 | 81 | if pixelcolor[0]+pixelcolor[1]+pixelcolor[2] == 0: 82 | share1.putpixel((x * 2, y * 2), (255,0,0,0)) 83 | share1.putpixel((x * 2 + 1, y * 2), (0,0,0,0)) 84 | share1.putpixel((x * 2, y * 2 + 1), (0,0,0,0)) 85 | share1.putpixel((x * 2 + 1, y * 2 + 1), (255,0,0,0)) 86 | 87 | else: 88 | share1.putpixel((x * 2, y * 2), (0,0,0,0)) 89 | share1.putpixel((x * 2 + 1, y * 2), (255,0,0,0)) 90 | share1.putpixel((x * 2, y * 2 + 1), (255,0,0,0)) 91 | share1.putpixel((x * 2 + 1, y * 2 + 1), (0,0,0,0)) 92 | 93 | pixelcolor = image2.getpixel((x, y)) 94 | 95 | if pixelcolor[0]+pixelcolor[1]+pixelcolor[2] == 0: 96 | share2.putpixel((x * 2, y * 2), (0,255,0,0)) 97 | share2.putpixel((x * 2 + 1, y * 2), (0,0,0,0)) 98 | share2.putpixel((x * 2, y * 2 + 1), (0,0,0,0)) 99 | share2.putpixel((x * 2 + 1, y * 2 + 1), (0,255,0,0)) 100 | 101 | else: 102 | share2.putpixel((x * 2, y * 2), (0,0,0,0)) 103 | share2.putpixel((x * 2 + 1, y * 2), (0,255,0,0)) 104 | share2.putpixel((x * 2, y * 2 + 1), (0,255,0,0)) 105 | share2.putpixel((x * 2 + 1, y * 2 + 1), (0,0,0,0)) 106 | 107 | pixelcolor = image3.getpixel((x, y)) 108 | 109 | if pixelcolor[0]+pixelcolor[1]+pixelcolor[2] == 0: 110 | share3.putpixel((x * 2, y * 2), (0,0,255,0)) 111 | share3.putpixel((x * 2 + 1, y * 2), (0,0,0,0)) 112 | share3.putpixel((x * 2, y * 2 + 1), (0,0,0,0)) 113 | share3.putpixel((x * 2 + 1, y * 2 + 1), (0,0,255,0)) 114 | 115 | else: 116 | share3.putpixel((x * 2, y * 2), (0,0,0,0)) 117 | share3.putpixel((x * 2 + 1, y * 2), (0,0,255,0)) 118 | share3.putpixel((x * 2, y * 2 + 1), (0,0,255,0)) 119 | share3.putpixel((x * 2 + 1, y * 2 + 1), (0,0,0,0)) 120 | 121 | share1.save('outputs/CMYK_Share3_1.jpg') 122 | share2.save('outputs/CMYK_Share3_2.jpg') 123 | share3.save('outputs/CMYK_Share3_3.jpg') 124 | 125 | print("Generated Shares!") 126 | 127 | def combineShares(): 128 | infile1 = Image.open('outputs/CMYK_Share3_1.jpg') 129 | infile2 = Image.open('outputs/CMYK_Share3_2.jpg') 130 | infile3 = Image.open('outputs/CMYK_Share3_1.jpg') 131 | 132 | outfile = Image.new('CMYK', infile1.size) 133 | 134 | for x in range(0,infile1.size[0],2): 135 | for y in range(0,infile1.size[1],2): 136 | 137 | C = infile1.getpixel((x+1, y))[0] 138 | M = infile2.getpixel((x+1, y))[1] 139 | Y = infile3.getpixel((x+1, y))[2] 140 | 141 | 142 | outfile.putpixel((x, y), (C,M,Y,0)) 143 | outfile.putpixel((x+1, y), (C,M,Y,0)) 144 | outfile.putpixel((x, y+1), (C,M,Y,0)) 145 | outfile.putpixel((x+1, y+1), (C,M,Y,0)) 146 | 147 | print("Combined Shares!") 148 | return outfile 149 | 150 | 151 | if __name__ == "__main__": 152 | 153 | print("Save input image as 'Input.png' in the same folder as this file\n") 154 | 155 | try: 156 | input_image = Image.open('Input.png') 157 | 158 | except FileNotFoundError: 159 | print("Input file not found!") 160 | exit(0) 161 | 162 | print("Image uploaded successfully!") 163 | print("Input image size (in pixels) : ", input_image.size) 164 | print("Number of shares image = ", 2, "\n") 165 | 166 | input_matrix = CMYK_Decomposition(input_image) 167 | halftoneConversion() 168 | generateShares() 169 | output_image = combineShares() 170 | 171 | output_image = output_image.resize(input_image.size) 172 | output_image.save('outputs/Output_CMYK.jpg', mode = "CMYK") 173 | print("\nImage is saved 'Output_CMYK.jpg' ...") 174 | 175 | output_image = Image.open('outputs/Output_CMYK.jpg') 176 | if output_image.mode == 'CMYK': 177 | output_image = output_image.convert('RGB') 178 | output_matrix = np.asarray(output_image) 179 | print("Output Image Size: ", output_matrix.shape) 180 | print("Evaluation metrics : ") 181 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 182 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Colour Images/Input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/Input.png -------------------------------------------------------------------------------- /Colour Images/ModularArithmetic_Implementation.py: -------------------------------------------------------------------------------- 1 | # Modular Arithmetic implementation for Colour Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from ColourMetrics import psnr, normxcorr2D 6 | 7 | def encrypt(input_image, share_size): 8 | image = np.asarray(input_image) 9 | (row, column, depth) = image.shape 10 | shares = np.random.randint(0, 256, size=(row, column, depth, share_size)) 11 | shares[:,:,:,-1] = image.copy() 12 | for i in range(share_size-1): 13 | shares[:,:,:,-1] = (shares[:,:,:,-1] + shares[:,:,:,i])%256 14 | 15 | return shares, image 16 | 17 | def decrypt(shares): 18 | (row, column, depth, share_size) = shares.shape 19 | shares_image = shares.copy() 20 | for i in range(share_size-1): 21 | shares_image[:,:,:,-1] = (shares_image[:,:,:,-1] - shares_image[:,:,:,i] + 256)%256 22 | 23 | final_output = shares_image[:,:,:,share_size-1] 24 | output_image = Image.fromarray(final_output.astype(np.uint8)) 25 | return output_image, final_output 26 | 27 | 28 | if __name__ == "__main__": 29 | 30 | print("Save input image as 'Input.png' in the same folder as this file\n") 31 | 32 | try: 33 | share_size = int(input("Input the number of shares images you want to create for encrypting (min is 2, max is 8) : ")) 34 | if share_size < 2 or share_size > 8: 35 | raise ValueError 36 | except ValueError: 37 | print("Input is not a valid integer!") 38 | exit(0) 39 | 40 | 41 | try: 42 | input_image = Image.open('Input.png') 43 | 44 | except FileNotFoundError: 45 | print("Input file not found!") 46 | exit(0) 47 | 48 | print("Image uploaded successfully!") 49 | print("Input image size (in pixels) : ", input_image.size) 50 | print("Number of shares image = ", share_size) 51 | 52 | shares, input_matrix = encrypt(input_image, share_size) 53 | 54 | for ind in range(share_size): 55 | image = Image.fromarray(shares[:,:,:,ind].astype(np.uint8)) 56 | name = "outputs/MA_Share_" + str(ind+1) + ".png" 57 | image.save(name) 58 | 59 | output_image, output_matrix = decrypt(shares) 60 | 61 | output_image.save('outputs/Output_MA.png') 62 | print("Image is saved 'Output_MA.png' ...") 63 | 64 | print("Evaluation metrics : ") 65 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 66 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Colour Images/README.md: -------------------------------------------------------------------------------- 1 | # Visual Cryptography for Colour images -------------------------------------------------------------------------------- /Colour Images/XOR_Implementation.py: -------------------------------------------------------------------------------- 1 | # XOR implementation for Colour Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from ColourMetrics import psnr, normxcorr2D 6 | 7 | def encrypt(input_image, share_size): 8 | image = np.asarray(input_image) 9 | (row, column, depth) = image.shape 10 | shares = np.random.randint(0, 256, size=(row, column, depth, share_size)) 11 | shares[:,:,:,-1] = image.copy() 12 | for i in range(share_size-1): 13 | shares[:,:,:,-1] = shares[:,:,:,-1] ^ shares[:,:,:,i] 14 | 15 | return shares, image 16 | 17 | def decrypt(shares): 18 | (row, column, depth, share_size) = shares.shape 19 | shares_image = shares.copy() 20 | for i in range(share_size-1): 21 | shares_image[:,:,:,-1] = shares_image[:,:,:,-1] ^ shares_image[:,:,:,i] 22 | 23 | final_output = shares_image[:,:,:,share_size-1] 24 | output_image = Image.fromarray(final_output.astype(np.uint8)) 25 | return output_image, final_output 26 | 27 | 28 | if __name__ == "__main__": 29 | 30 | print("Save input image as 'Input.png' in the same folder as this file\n") 31 | 32 | try: 33 | share_size = int(input("Input the number of shares images you want to create for encrypting (min is 2, max is 8) : ")) 34 | if share_size < 2 or share_size > 8: 35 | raise ValueError 36 | except ValueError: 37 | print("Input is not a valid integer!") 38 | exit(0) 39 | 40 | 41 | try: 42 | input_image = Image.open('Input.png') 43 | 44 | except FileNotFoundError: 45 | print("Input file not found!") 46 | exit(0) 47 | 48 | print("Image uploaded successfully!") 49 | print("Input image size (in pixels) : ", input_image.size) 50 | print("Number of shares image = ", share_size) 51 | 52 | shares, input_matrix = encrypt(input_image, share_size) 53 | 54 | for ind in range(share_size): 55 | image = Image.fromarray(shares[:,:,:,ind].astype(np.uint8)) 56 | name = "outputs/XOR_Share_" + str(ind+1) + ".png" 57 | image.save(name) 58 | 59 | output_image, output_matrix = decrypt(shares) 60 | 61 | output_image.save('outputs/Output_XOR.png') 62 | print("Image is saved 'Output_XOR.png' ...") 63 | 64 | print("Evaluation metrics : ") 65 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 66 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share1_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share1_1.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share1_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share1_2.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share1_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share1_3.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share2_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share2_1.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share2_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share2_2.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share2_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share2_3.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share3_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share3_1.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share3_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share3_2.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/CMYK_Share3_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/CMYK_Share3_3.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/MA_Share_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/MA_Share_1.png -------------------------------------------------------------------------------- /Colour Images/outputs/MA_Share_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/MA_Share_2.png -------------------------------------------------------------------------------- /Colour Images/outputs/Output_CMYK.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/Output_CMYK.jpg -------------------------------------------------------------------------------- /Colour Images/outputs/Output_MA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/Output_MA.png -------------------------------------------------------------------------------- /Colour Images/outputs/Output_XOR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/Output_XOR.png -------------------------------------------------------------------------------- /Colour Images/outputs/XOR_Share_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/XOR_Share_1.png -------------------------------------------------------------------------------- /Colour Images/outputs/XOR_Share_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Colour Images/outputs/XOR_Share_2.png -------------------------------------------------------------------------------- /Grayscale Images/BitLevelDecomposition_Implementation.py: -------------------------------------------------------------------------------- 1 | # Pixel Expansion implementation for Binary Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from GrayscaleMetrics import psnr, normxcorr2D 6 | 7 | def extract_colour(): 8 | colour = [[0,0,1,1], [1,1,0,0], [1,0,0,1],[0,1,1,0],[1,0,1,0],[0,1,0,1]] 9 | return np.array(colour[np.random.randint(0,6)]) 10 | 11 | 12 | def PE_encrypt(input_matrix): 13 | 14 | (row, column) = input_matrix.shape 15 | secret_share1 = np.empty((2*row, 2*column)).astype('uint8') 16 | secret_share2 = np.empty((2*row, 2*column)).astype('uint8') 17 | 18 | for i in range(row): 19 | for j in range(column): 20 | colour = extract_colour() 21 | secret_share1[2*i][2*j] = secret_share2[2*i][2*j] = colour[0] 22 | secret_share1[2*i + 1][2*j] = secret_share2[2*i + 1][2*j] = colour[1] 23 | secret_share1[2*i][2*j + 1] = secret_share2[2*i][2*j + 1] = colour[2] 24 | secret_share1[2*i + 1][2*j + 1] = secret_share2[2*i + 1][2*j + 1] = colour[3] 25 | 26 | if input_matrix[i][j] == 0: 27 | secret_share2[2*i][2*j] = 1 - secret_share2[2*i][2*j] 28 | secret_share2[2*i + 1][2*j] = 1 - secret_share2[2*i + 1][2*j] 29 | secret_share2[2*i][2*j + 1] = 1 - secret_share2[2*i][2*j + 1] 30 | secret_share2[2*i + 1][2*j + 1] = 1 - secret_share2[2*i + 1][2*j + 1] 31 | 32 | return secret_share1, secret_share2 33 | 34 | 35 | def PE_decrypt(secret_share1, secret_share2): 36 | ''' 37 | Black -> 0 38 | White -> 1 39 | 40 | White + White -> White ( 1 + 1 -> 1) 41 | White + Black -> Black ( 1 + 0 -> 0) 42 | Black + White -> Black ( 0 + 1 -> 0) 43 | Black + Black -> Black ( 0 + 0 -> 0) 44 | 45 | Best operator to use for this is - bitwise and 46 | 47 | ''' 48 | overlap_matrix = secret_share1 & secret_share2 49 | (row, column) = secret_share1.shape 50 | row = int(row/2) 51 | column = int(column/2) 52 | extraction_matrix = np.ones((row, column)) 53 | 54 | for i in range(row): 55 | for j in range(column): 56 | cnt = overlap_matrix[2*i][2*j] + overlap_matrix[2*i + 1][2*j] + overlap_matrix[2*i][2*j + 1] + overlap_matrix[2*i + 1][2*j + 1] 57 | if cnt == 0: 58 | extraction_matrix[i][j] = 0 59 | 60 | return overlap_matrix, extraction_matrix 61 | 62 | 63 | def convertGrayToBinary(image): 64 | grayScaleImage = image.copy() 65 | (row, column) = grayScaleImage.shape 66 | binaryImage = np.ones((row, column, 8)) 67 | for i in range(8): 68 | binaryImage[:,:,i] = (grayScaleImage.copy())%2 69 | grayScaleImage = (grayScaleImage/2).astype('uint8') 70 | 71 | return binaryImage 72 | 73 | 74 | def convertBinaryToGray(image): 75 | binaryImage = image.copy() 76 | (row, column, _) = binaryImage.shape 77 | grayScaleImage = np.zeros((row, column)) 78 | for i in range(8): 79 | grayScaleImage = (grayScaleImage*2 + binaryImage[:,:,7-i]).astype('uint8') 80 | 81 | return grayScaleImage 82 | 83 | 84 | def BLD_encrypt(input_image): 85 | input_matrix = np.asarray(input_image) 86 | binaryDecomposition = convertGrayToBinary(input_matrix.copy()) 87 | 88 | (row, column, _) = binaryDecomposition.shape 89 | 90 | binaryShareImage_1 = np.zeros((2*row, 2*column, 8)).astype('uint8') 91 | binaryShareImage_2 = np.zeros((2*row, 2*column, 8)).astype('uint8') 92 | 93 | for index in range(8): 94 | binaryShareImage_1[:,:,index], binaryShareImage_2[:,:,index] = PE_encrypt(binaryDecomposition[:,:,index]) 95 | 96 | secret_share1 = convertBinaryToGray(binaryShareImage_1) 97 | secret_share2 = convertBinaryToGray(binaryShareImage_2) 98 | 99 | return secret_share1, secret_share2, input_matrix 100 | 101 | 102 | def BLD_decrypt(secret_share1, secret_share2): 103 | binaryShareImage_1 = convertGrayToBinary(secret_share1) 104 | binaryShareImage_2 = convertGrayToBinary(secret_share2) 105 | 106 | binaryShareImage_1 = binaryShareImage_1.astype('uint8') 107 | binaryShareImage_2 = binaryShareImage_2.astype('uint8') 108 | 109 | 110 | (row, column, _) = binaryShareImage_1.shape 111 | 112 | binaryOverlapMatrix = np.zeros((row, column, 8)).astype('uint8') 113 | binaryExtractionMatrix = np.zeros((int(row/2), int(column/2), 8)).astype('uint8') 114 | 115 | for index in range(8): 116 | binaryOverlapMatrix[:,:,index], binaryExtractionMatrix[:,:,index] = PE_decrypt(binaryShareImage_1[:,:,index], binaryShareImage_2[:,:,index]) 117 | 118 | overlap_matrix = convertBinaryToGray(binaryOverlapMatrix) 119 | extraction_matrix = convertBinaryToGray(binaryExtractionMatrix) 120 | 121 | return overlap_matrix, extraction_matrix 122 | 123 | 124 | if __name__ == "__main__": 125 | 126 | print("Save input image as 'Input.png' in the same folder as this file\n") 127 | 128 | try: 129 | input_image = Image.open('Input.png').convert('L') 130 | 131 | except FileNotFoundError: 132 | print("Input file not found!") 133 | exit(0) 134 | 135 | print("Image uploaded successfully!") 136 | print("Input image size (in pixels) : ", input_image.size) 137 | print("Number of shares image = 2") 138 | 139 | secret_share1, secret_share2, input_matrix = BLD_encrypt(input_image) 140 | 141 | image1 = Image.fromarray(secret_share1.astype(np.uint8)) 142 | image1.save("outputs/BLD_SecretShare_1.png") 143 | image2 = Image.fromarray(secret_share2.astype(np.uint8)) 144 | image2.save("outputs/BLD_SecretShare_2.png") 145 | 146 | overlap_matrix, extraction_matrix = BLD_decrypt(secret_share1, secret_share2) 147 | extraction_output = Image.fromarray(extraction_matrix.astype(np.uint8)) 148 | overlap_output = Image.fromarray(overlap_matrix.astype(np.uint8)) 149 | 150 | extraction_output.save('outputs/Output_BLD(Extraction).png', mode = '1') 151 | print("Image is saved 'Output_BLD(Extraction).png' ...") 152 | 153 | overlap_output = overlap_output.resize(input_image.size) 154 | overlap_matrix = np.asarray(overlap_output).astype(np.uint8) 155 | overlap_output.save('outputs/Output_BLD(Overlap).png', mode = '1') 156 | print("Image is saved 'Output_BLD(Overlap).png' ...\n\n") 157 | 158 | print("Evaluation metrics for Extraction algorithm: ") 159 | print(f"PSNR value is {psnr(input_matrix, extraction_matrix)} dB") 160 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, extraction_matrix)}") 161 | 162 | print("\n\nEvaluation metrics for Overlap algorithm: ") 163 | print(f"PSNR value is {psnr(input_matrix, overlap_matrix)} dB") 164 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, overlap_matrix)}") 165 | 166 | -------------------------------------------------------------------------------- /Grayscale Images/GrayscaleMetrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | from scipy import signal 4 | from PIL import Image 5 | 6 | def normxcorr2D(image, template): 7 | """ 8 | Normalized cross-correlation for 2D PIL images 9 | Adapted from: https://github.com/JustinLiang/ComputerVisionProjects/ 10 | Inputs: 11 | ---------------- 12 | template The template. A PIL image. Elements cannot all be equal. 13 | image The PIL image. 14 | Output: 15 | ---------------- 16 | nxcorr Array of cross-correlation coefficients, in the range 17 | -1.0 to 1.0. Size == Input image and template shape 18 | Wherever the search space has zero variance under the template, 19 | normalized cross-correlation is undefined. 20 | """ 21 | 22 | # (one-time) normalization of template 23 | t = np.asarray(template, dtype=np.float64) 24 | t = t - np.mean(t) 25 | norm = math.sqrt(np.sum(np.square(t))) 26 | if norm == 0: 27 | raise ValueError("Norm of the input is 0") 28 | t = t / norm 29 | 30 | # create filter to sum values under template 31 | sum_filter = np.ones(np.shape(t)) 32 | 33 | # get image 34 | a = np.asarray(image, dtype=np.float64) 35 | #also want squared values 36 | aa = np.square(a) 37 | 38 | # compute sums of values and sums of values squared under template 39 | a_sum = signal.correlate(a, sum_filter, 'same') 40 | aa_sum = signal.correlate(aa, sum_filter, 'same') 41 | # Note: The above two lines could be made more efficient by 42 | # exploiting the fact that sum_filter is separable. 43 | # Even better would be to take advantage of integral images 44 | 45 | # compute correlation, 't' is normalized, 'a' is not (yet) 46 | numer = signal.correlate(a, t, 'same') 47 | # (each time) normalization of the window under the template 48 | denom = np.sqrt(aa_sum - np.square(a_sum)/np.size(t)) 49 | 50 | # wherever the denominator is near zero, this must be because the image 51 | # window is near constant (and therefore the normalized cross correlation 52 | # is undefined). Set nxcorr to zero in these regions 53 | tol = np.sqrt(np.finfo(denom.dtype).eps) 54 | nxcorr = np.where(denom < tol, 0, numer/denom) 55 | 56 | # if any of the coefficients are outside the range [-1 1], they will be 57 | # unstable to small variance in a or t, so set them to zero to reflect 58 | # the undefined 0/0 condition 59 | nxcorr = np.where(np.abs(nxcorr-1.) > np.sqrt(np.finfo(nxcorr.dtype).eps),nxcorr,0) 60 | 61 | return np.mean(nxcorr) 62 | 63 | 64 | def psnr(original, contrast): 65 | mse = np.mean((original - contrast) ** 2) 66 | if mse == 0: 67 | return 100 68 | PIXEL_MAX = 255.0 69 | PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) 70 | return PSNR -------------------------------------------------------------------------------- /Grayscale Images/Input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/Input.png -------------------------------------------------------------------------------- /Grayscale Images/ModularArithmetic_Implementation.py: -------------------------------------------------------------------------------- 1 | # Modular Arithmetic implementation for Grayscale Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from GrayscaleMetrics import psnr, normxcorr2D 6 | 7 | def encrypt(input_image, share_size): 8 | image = np.asarray(input_image) 9 | (row, column) = image.shape 10 | shares = np.random.randint(0, 256, size=(row, column, share_size)) 11 | shares[:,:,-1] = image.copy() 12 | for i in range(share_size-1): 13 | shares[:,:,-1] = (shares[:,:,-1] + shares[:,:,i])%256 14 | 15 | return shares, image 16 | 17 | def decrypt(shares): 18 | (row, column, share_size) = shares.shape 19 | shares_image = shares.copy() 20 | for i in range(share_size-1): 21 | shares_image[:,:,-1] = (shares_image[:,:,-1] - shares_image[:,:,i] + 256)%256 22 | 23 | final_output = shares_image[:,:,share_size-1] 24 | output_image = Image.fromarray(final_output.astype(np.uint8)) 25 | return output_image, final_output 26 | 27 | 28 | if __name__ == "__main__": 29 | 30 | print("Save input image as 'Input.png' in the same folder as this file\n") 31 | 32 | try: 33 | share_size = int(input("Input the number of shares images you want to create for encrypting (min is 2, max is 8) : ")) 34 | if share_size < 2 or share_size > 8: 35 | raise ValueError 36 | except ValueError: 37 | print("Input is not a valid integer!") 38 | exit(0) 39 | 40 | 41 | try: 42 | input_image = Image.open('Input.png').convert('L') 43 | 44 | except FileNotFoundError: 45 | print("Input file not found!") 46 | exit(0) 47 | 48 | print("Image uploaded successfully!") 49 | print("Input image size (in pixels) : ", input_image.size) 50 | print("Number of shares image = ", share_size) 51 | 52 | shares, input_matrix = encrypt(input_image, share_size) 53 | 54 | for ind in range(share_size): 55 | image = Image.fromarray(shares[:,:,ind].astype(np.uint8)) 56 | name = "outputs/MA_Share_" + str(ind+1) + ".png" 57 | image.save(name) 58 | 59 | output_image, output_matrix = decrypt(shares) 60 | 61 | output_image.save('outputs/Output_MA.png') 62 | print("Image is saved 'Output_MA.png' ...") 63 | 64 | print("Evaluation metrics : ") 65 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 66 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Grayscale Images/README.md: -------------------------------------------------------------------------------- 1 | # Visual Cryptography for Grayscale images -------------------------------------------------------------------------------- /Grayscale Images/XOR_Implementation.py: -------------------------------------------------------------------------------- 1 | # XOR implementation for Grayscale Image 2 | 3 | import numpy as np 4 | from PIL import Image 5 | from GrayscaleMetrics import psnr, normxcorr2D 6 | 7 | def encrypt(input_image, share_size): 8 | image = np.asarray(input_image) 9 | (row, column) = image.shape 10 | shares = np.random.randint(0, 256, size=(row, column, share_size)) 11 | shares[:,:,-1] = image.copy() 12 | for i in range(share_size-1): 13 | shares[:,:,-1] = shares[:,:,-1] ^ shares[:,:,i] 14 | 15 | return shares, image 16 | 17 | def decrypt(shares): 18 | (row, column, share_size) = shares.shape 19 | shares_image = shares.copy() 20 | for i in range(share_size-1): 21 | shares_image[:,:,-1] = shares_image[:,:,-1] ^ shares_image[:,:,i] 22 | 23 | final_output = shares_image[:,:,share_size-1] 24 | output_image = Image.fromarray(final_output.astype(np.uint8)) 25 | return output_image, final_output 26 | 27 | 28 | if __name__ == "__main__": 29 | 30 | print("Save input image as 'Input.png' in the same folder as this file\n") 31 | 32 | try: 33 | share_size = int(input("Input the number of shares images you want to create for encrypting (min is 2, max is 8) : ")) 34 | if share_size < 2 or share_size > 8: 35 | raise ValueError 36 | except ValueError: 37 | print("Input is not a valid integer!") 38 | exit(0) 39 | 40 | 41 | try: 42 | input_image = Image.open('Input.png').convert('L') 43 | 44 | except FileNotFoundError: 45 | print("Input file not found!") 46 | exit(0) 47 | 48 | print("Image uploaded successfully!") 49 | print("Input image size (in pixels) : ", input_image.size) 50 | print("Number of shares image = ", share_size) 51 | 52 | shares, input_matrix = encrypt(input_image, share_size) 53 | 54 | for ind in range(share_size): 55 | image = Image.fromarray(shares[:,:,ind].astype(np.uint8)) 56 | name = "outputs/XOR_Share_" + str(ind+1) + ".png" 57 | image.save(name) 58 | 59 | output_image, output_matrix = decrypt(shares) 60 | 61 | output_image.save('outputs/Output_XOR.png') 62 | print("Image is saved 'Output_XOR.png' ...") 63 | 64 | print("Evaluation metrics : ") 65 | print(f"PSNR value is {psnr(input_matrix, output_matrix)} dB") 66 | print(f"Mean NCORR value is {normxcorr2D(input_matrix, output_matrix)}") -------------------------------------------------------------------------------- /Grayscale Images/outputs/BLD_SecretShare_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/BLD_SecretShare_1.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/BLD_SecretShare_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/BLD_SecretShare_2.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/MA_Share_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/MA_Share_1.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/MA_Share_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/MA_Share_2.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/Output_BLD(Extraction).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/Output_BLD(Extraction).png -------------------------------------------------------------------------------- /Grayscale Images/outputs/Output_BLD(Overlap).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/Output_BLD(Overlap).png -------------------------------------------------------------------------------- /Grayscale Images/outputs/Output_MA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/Output_MA.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/Output_XOR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/Output_XOR.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/XOR_Share_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/XOR_Share_1.png -------------------------------------------------------------------------------- /Grayscale Images/outputs/XOR_Share_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Grayscale Images/outputs/XOR_Share_2.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Visual-Cryptography 2 | 3 | **Visual Cryptography** is a cryptographic technique to encrypt visual information like images and text, which doesn’t require any sophisticated computation but a mere human sight-reading to decrypt. Visual Cryptography uses the idea of hiding secrets within images which are divided into multiple shares and then decoded by superimposing the shared images. 4 | 5 | This is a Visual Cryptography implementation as part of Cryptography course project (CS350 and CS353). In this project, the following methods are implemented based on the types of images: binary, grayscale, and colored. 6 | 1. XOR implementation (Binary, Grayscale, and Colour) 7 | 2. Modular Arithmetic Implementation (Binary, Grayscale, and Colour) 8 | 3. Pixel expansion implementation (Binary) 9 | 4. Key + AES encryption implementation (Binary, Grayscale, and Colour) 10 | 5. Halftone CMYK Decomposition (Colour) 11 | 6. Bit-Level Decomposition (Grayscale) 12 | 13 | We have planned to use PSNR (Peak Signal-to-Noise Ratio) and NCC (Normalized Cross-Correlation) as a metric to check how the final decrypted image is similar(or related) to the original image. 14 | 15 | ## Team Members 16 | 1. [Shreeraksha R Aithal](https://github.com/Shree987) (181CO149) 17 | 2. [K Krishna Swaroop](https://github.com/geekswaroop) (181CO125) 18 | 19 | ## Reference Materials 20 | * [Visual Cryptography](https://link.springer.com/content/pdf/10.1007/BFb0053419.pdf) 21 | * [Applications and usage of visual cryptography: A review](https://ieeexplore.ieee.org/document/7784984) 22 | * [Visual Cryptography for Gray-scale Images Using 23 | Bit-level](http://bit.kuas.edu.tw/~jihmsp/2014/vol5/JIH-MSP-2014-01-010.pdf) 24 | * [An Implementation of Algorithms in Visual Cryptography in Images](http://www.ijsrp.org/research-paper-0313/ijsrp-p1574.pdf) 25 | * [Copyright protection scheme for digital images using visual cryptography and sampling methods](https://www.researchgate.net/publication/243483757_Copyright_protection_scheme_for_digital_images_using_visual_cryptography_and_sampling_methods) 26 | * [Visual Cryptography in Gray Scale Images](http://www.ijerd.com/paper/vol8-issue4/I08046568.pdf) 27 | * [A novel image encryption algorithm using AES and visual cryptography](https://ieeexplore.ieee.org/document/7877521) 28 | * [Visual cryptography for color images](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.457.5077&rep=rep1&type=pdf) 29 | * [Improving Image Quality In Extended Visual Cryptography For Halftone Images With No Pixel Expansion](http://www.ijstr.org/final-print/apr2014/Improving-Image-Quality-In-Extended-Visual-Cryptography-For-Halftone-Images-With-No-Pixel-Expansion.pdf) 30 | -------------------------------------------------------------------------------- /Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Report.pdf -------------------------------------------------------------------------------- /Screenshots/Binary Images/Modular Arithmetic Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Binary Images/Modular Arithmetic Implementation.png -------------------------------------------------------------------------------- /Screenshots/Binary Images/Pixel Expansion Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Binary Images/Pixel Expansion Implementation.png -------------------------------------------------------------------------------- /Screenshots/Binary Images/XOR Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Binary Images/XOR Implementation.png -------------------------------------------------------------------------------- /Screenshots/Colour Images/Modular Arithmetic Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Colour Images/Modular Arithmetic Implementation.png -------------------------------------------------------------------------------- /Screenshots/Colour Images/XOR Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Colour Images/XOR Implementation.png -------------------------------------------------------------------------------- /Screenshots/Grayscale Images/Bit Level Decomposition Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Grayscale Images/Bit Level Decomposition Implementation.png -------------------------------------------------------------------------------- /Screenshots/Grayscale Images/Modular Arithmetic Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Grayscale Images/Modular Arithmetic Implementation.png -------------------------------------------------------------------------------- /Screenshots/Grayscale Images/XOR Implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shree987/Visual-Cryptography/58b36c0d684d473af4f81e91f48ceaca1bb776d3/Screenshots/Grayscale Images/XOR Implementation.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib==3.3.3 2 | numpy==1.19.5 3 | opencv-python==4.5.1.48 4 | pandas==1.2.1 5 | Pillow==8.1.0 6 | pycrypto==2.6.1 7 | scikit-learn==0.24.1 8 | scipy==1.6.0 9 | -------------------------------------------------------------------------------- /utils/ncorr.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | from scipy import signal 4 | from PIL import Image 5 | 6 | def normxcorr2D(image, template): 7 | """ 8 | Normalized cross-correlation for 2D PIL images 9 | Adapted from: https://github.com/JustinLiang/ComputerVisionProjects/ 10 | Inputs: 11 | ---------------- 12 | template The template. A PIL image. Elements cannot all be equal. 13 | image The PIL image. 14 | Output: 15 | ---------------- 16 | nxcorr Array of cross-correlation coefficients, in the range 17 | -1.0 to 1.0. Size == Input image and template shape 18 | Wherever the search space has zero variance under the template, 19 | normalized cross-correlation is undefined. 20 | """ 21 | 22 | # (one-time) normalization of template 23 | t = np.asarray(template, dtype=np.float64) 24 | t = t - np.mean(t) 25 | norm = math.sqrt(np.sum(np.square(t))) 26 | if norm != 0: 27 | t = t / norm 28 | 29 | # create filter to sum values under template 30 | sum_filter = np.ones(np.shape(t)) 31 | 32 | # get image 33 | a = np.asarray(image, dtype=np.float64) 34 | #also want squared values 35 | aa = np.square(a) 36 | 37 | # compute sums of values and sums of values squared under template 38 | a_sum = signal.correlate(a, sum_filter, 'same') 39 | aa_sum = signal.correlate(aa, sum_filter, 'same') 40 | # Note: The above two lines could be made more efficient by 41 | # exploiting the fact that sum_filter is separable. 42 | # Even better would be to take advantage of integral images 43 | 44 | # compute correlation, 't' is normalized, 'a' is not (yet) 45 | numer = signal.correlate(a, t, 'same') 46 | # (each time) normalization of the window under the template 47 | denom = np.sqrt(aa_sum - np.square(a_sum)/np.size(t)) 48 | 49 | # wherever the denominator is near zero, this must be because the image 50 | # window is near constant (and therefore the normalized cross correlation 51 | # is undefined). Set nxcorr to zero in these regions 52 | tol = np.sqrt(np.finfo(denom.dtype).eps) 53 | nxcorr = np.where(denom < tol, 0, numer/denom) 54 | 55 | # if any of the coefficients are outside the range [-1 1], they will be 56 | # unstable to small variance in a or t, so set them to zero to reflect 57 | # the undefined 0/0 condition 58 | nxcorr = np.where(np.abs(nxcorr-1.) > np.sqrt(np.finfo(nxcorr.dtype).eps),nxcorr,0) 59 | 60 | return np.mean(nxcorr) 61 | 62 | def test_ncorr(): 63 | 64 | image = Image.open('../Input.png') 65 | contrast_image = Image.open('../Output.png') 66 | print(f"Mean NCORR value is {normxcorr2D(image, contrast_image)}") 67 | 68 | if __name__ == '__main__': 69 | test_ncorr() 70 | 71 | -------------------------------------------------------------------------------- /utils/psnr.py: -------------------------------------------------------------------------------- 1 | ## Adapted from https://tutorials.techonical.com/how-to-calculate-psnr-value-of-two-images-using-python/ 2 | import math 3 | import os 4 | import numpy as np 5 | from PIL import Image 6 | 7 | def psnr(original, contrast): 8 | mse = np.mean((original - contrast) ** 2) 9 | if mse == 0: 10 | return 100 11 | PIXEL_MAX = 255.0 12 | PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) 13 | return PSNR 14 | 15 | def test_psnr(): 16 | image = Image.open('../../Basic implementation/Shared key.png') 17 | contrast_image = Image.open('../../Basic implementation/Noise image.png') 18 | 19 | image = np.asarray(image) 20 | contrast_image = np.asarray(contrast_image) 21 | print(f"PSNR value is {psnr(image, contrast_image)} dB") 22 | 23 | 24 | if __name__ == '__main__': 25 | test_psnr() --------------------------------------------------------------------------------