3 #############################################
4 # Script réalisé dans le cadre du papier
5 # concernant l'utilisation de plusieurs
6 # fonctions chaotiques (pas seulement la
7 # négation vectorielle) pour le tatouage.
9 # On utilise 3 fonctions différentes, on tatoue
10 # dans le domaine ondelette.
11 #############################################
14 from sobel555_for_ensemble import *
17 #from outilsBase import conversion, getBit, setBit
19 from copy import deepcopy
21 from ImageChops import difference
22 from attaque import Attaque
24 def matrice_to_bits(matrice):
26 Renvoie la matrice des écritures binaires de matrice.
27 Les coefficients floants deviennent des chaînes (str) de bits.
34 ligne.append(conversion(str(matrice[l,c]),2))
40 def matrice_lscs(matrice,lscs):
42 Matrice est une liste de listes, lscs est une liste.
44 A partir d'une matrice de coefficients binaires, vus comme
45 des chaines de caractères, extrait les bits dont les positions
46 sont données par la liste lscs.
48 Dans la liste lscs, un entier positif signifie devant la virgule,
49 un entier négatif signifie derrière. Le premier bit devant la
50 virgule est le bit 1, le premier bit derrière la virgule est le -1.
52 Le retour est une liste de bits (entiers).
54 m,n = len(matrice), len(matrice[0])
58 #num = str(round(float(matrice[l][c]),2))
62 ent,dec = num.replace('-',''),'0'
64 ent,dec = num.replace('-','').split('.')
65 ent,dec = list(ent),list(dec)
68 if lsc > 0 and len(ent)>=lsc:
69 retour.append(ent[lsc-1])
70 elif lsc<0 and len(dec)>=abs(lsc):
71 retour.append(dec[abs(lsc)-1])
74 return [int(k) for k in retour][:-3]
77 def embarque(liste,matrice,lscs):
78 m,n = len(matrice), len(matrice[0])
83 if '-' in matrice[l][c]:
87 if '.' not in matrice[l][c]:
88 ent,dec = matrice[l][c].replace('-',''),'0'
90 ent,dec = matrice[l][c].replace('-','').split('.')
91 ent,dec = list(ent),list(dec)
93 maximum = max([abs(k) for k in lscs])
94 ent = list(''.join(ent).zfill(maximum+2))
95 dec = list(''.join(dec).zfill(maximum+2))
99 ent[lsc-1] = str(liste[cpt])
101 dec[abs(lsc)-1] = str(liste[cpt])
113 retour = [int(not L[k]) for k in range(n)]
114 retour.extend([L[k-n] for k in range(n,2*n)])
115 retour.extend([int(L[k-2*n])*int(not L[k+1]) for k in range(2*n,4*n)])
116 retour.extend([int(not L[2*n])])
123 retour = [int(not L[0])]
124 retour.extend([L[k-1] for k in range(1,len(L))])
135 rl.append(int(not el))
137 rl.append(0 if sum(x[k-2:k])%2==0 else 1 )
149 r = 0 if sum(x[i-1:i+1])%2==0 else 1
159 def embarque2(liste,matrice,lscs):
161 m,n = len(matrice), len(matrice[0])
162 retour = deepcopy(matrice)
168 retour[l,c] = setBit(str(retour[l,c]),lsc, liste[cpt])
177 Retourne le PSNR entre deux images.
184 eqm+=(mat1[k][l] - mat2[k][l])**2
187 return 10*log(densite**2/r,10)
197 if mat1[k] != mat2[k] :
199 #print mat1[k],mat2[k]
200 return float(100)*cpt/lm
202 def arrondi_en_entier(mat):
204 return array([[round(mat[i][j]) for j in range(c)]for i in range(l)])
209 def sauve(data,outfile="dummy.png",file_msg="invader.png"):
210 (l,h)=im.open(file_msg).size
211 outIm = im.new('L',im.open(file_msg).size)
212 queue = [255 if x != 0 else 0 for x in data]
213 queue = queue[len(queue)-l*h:]
215 outIm.save("apresattaque.png")
220 def retrouve_message_parametre(file_msg="invader.png"):
222 bbs = BlumBlumShub();
227 for c in [x if x==0 else 1 for x in im.open(file_msg).getdata()]:
230 leng_msg=len(message)
231 leng='%08d'%len(message)
233 leng_error=int(len_leng)
235 List_pack=a2b_list(leng_cor)
238 leng_msg=len(List_pack)
241 while len(List_random)<leng_msg:
242 List_random.extend(Denary2Binary(bbs.next()))
245 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
246 return (leng_msg,Message,List_random)
252 def experience(nom_fichier,leng_msg,Message,List_random):
253 # print "message initial",Message
255 dd = im.open(nom_fichier)
256 dd = dd.convert('RGB')
257 red, green, blue = dd.split()
261 marquee_matrice = np.array(at.getdata()).reshape((l,h))
262 level= array(level.getdata()).flatten()
265 ############# construire ici les attaques
267 # matrices attaquees par rotation
268 attaquee_matrice = []
270 for k in range(nbexp):
271 at = Attaque.rotation(marquee_matrice,
275 m = [((abs(marquee_matrice-at)[i,j]),(i,j)) for i in xrange(l) for j in xrange(h)]
277 #m = sorted(m.items(), key=itemgetter(0))
279 print "diffence max", m
281 attaquee_matrice += [at]
285 # matrices attaquees compression jpeg
287 for k in range(nbexp):
288 at = Attaque.jpeg(marquee_matrice,
291 attaquee_matrice += [at]
294 # matrices attaquees compression jp2000
295 print "compression jp2000"
296 for k in range(nbexp):
297 at = Attaque.jp2(marquee_matrice,
300 attaquee_matrice += [at]
305 # matrices attaquees decoupage
306 for k in range(nbexp):
307 t = int(0.1*(k+1)*min(taillex,tailley))
308 at = Attaque.decoupage(marquee_matrice,
311 attaquee_matrice += [at]
314 # matrices attaquees flou
315 for k in range(nbexp):
317 at = Attaque.flou(marquee_matrice,t)
318 attaquee_matrice += [at]
321 # matrices attaquees contrast
322 for k in range(nbexp):
324 at = Attaque.contraste(marquee_matrice,t)
325 attaquee_matrice += [at]
328 # matrices attaquees redimensionnement
329 print "dimensionnement"
330 attaquee_matrice += [Attaque.redimensionnement(marquee_matrice,
333 attaquee_matrice += [Attaque.redimensionnement(marquee_matrice,
341 print "nombre d'attaques",len(attaquee_matrice)
346 for am in attaquee_matrice:
349 im2 = im.new('L',dd.size)
350 im2.putdata(attaquee.flatten())
351 im2.save("apresRot.png")
359 print im2,dd,leng_msg
360 [List_bit_to_change2,Weight2]=compute_filter_canny(im2,dd,leng_msg)
361 # on a mis dd et leng_msg : c'est juste pour la taille.
362 #level2= array(level.getdata()).flatten()
364 level2= array(im2.getdata()).flatten()
366 print "support2",len(List_bit_to_change2)
367 print "weight2",len(Weight2)
369 alpha = float(len(List_bit_to_change2))/len(Message)
371 index = min(int(alpha),9)
375 4 : [81, 95, 107, 121],
376 5 : [75, 95, 97, 105, 117],
377 6 : [73, 83, 95, 103, 109, 123],
378 7 : [69, 77, 93, 107, 111, 115, 121],
379 8 : [69, 79, 81, 89, 93, 99, 107, 119],
380 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
385 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change2]
386 LL2=list(List_bit_to_change2)
388 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message2))])
389 #print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message2))])
390 #print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
392 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
394 print "Message final",Message2
395 #print equiv(Message,Message2)
404 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
405 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
406 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
408 #print "MessageDecoded2",MessageDecoded2
409 #print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
412 sauve(MessageDecoded2)
414 return MessageDecoded2
422 path_stego = '/home/couchot/rech/CCG12/canny/stc/exp/raphus/stego/'
423 path_cover = '/home/couchot/rech/BCG10/Oxford11/experiments/images/'
426 listing = [957, 108, 106, 29, 431, 924, 262, 477, 346, 809]
428 (leng_msg,Message,List_random) = retrouve_message_parametre()
429 print "params :", leng_msg,len(Message),List_random[0:5]
430 for infile in listing:
432 fi = path_cover+str(infile)+'.png'
433 fo = path_stego+str(infile)+'.png'
434 experience(fo,leng_msg,Message,List_random)
437 if __name__ == "__main__":