15 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
16 X=18532395500947174450709383384936679868383424444311
32 acc = acc + 2**(n-i-1)
37 """Convertit un nombre en binaire"""
39 res = [0 for i in xrange(n)]
52 return 1 if a != b else 0
55 e1b,e2b = bin(e1,h),bin(e2,h)
56 d = dec([xorb(e1b[j],e2b[j]) for j in xrange(h)],h)
59 def lit(d,(indx,indy)):
68 def forward(H_hat,x,message,lnm,rho):
69 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
72 wght = [infinity for _ in xrange(int(2**h))]
74 newwght = [0 for _ in xrange(int(2**h))]
76 # rho= [1 for _ in xrange(len(x))]
79 while i < nbblock: # pour chaque bit du message
80 for j in xrange(w): # pour chaque colonne de H_hat
81 #print indx, "en entrant",wght
83 while k < int(2**h): # pour chaque ligne de H
84 w0 = wght[k] + x[indx]*rho[indx]
85 w1 = wght[xor(k,H_hat[j],h)] + (1-x[indx])*rho[indx]
91 newwght[k] = min(w0,w1)
94 wght = [t for t in newwght]
95 #print " apres calcul",wght
97 for j in xrange(int(2**(h-1))): # pour chaque colonne de H
98 wght[j] = wght[2*j + message[indm]]
99 wght = wght[:int(pow(2,h-1))] + [infinity for _ in xrange(int(pow(2,h)-pow(2,h-1)))]
102 start = np.argmin(wght)
106 def backward(start,H_hat,x,message,lnm,path):
107 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
108 indx,indm = len(x)-1,lnm-1
109 state = 2*start + message[indm]
111 # l'initialisation de state n'est pas optimale...
118 for j in l: # pour chaque colonne de H_hat
119 y[indx] = lit(path,(indx,state))
120 state = xor(state,y[indx]*H_hat[j],h)
122 state = 2*state + message[indm]
125 return [int(t) for t in y]
132 def trouve_H_hat(n,m,h):
136 index = min(int(alpha),9)
141 4 : [81, 95, 107, 121],
142 5 : [75, 95, 97, 105, 117],
143 6 : [73, 83, 95, 103, 109, 123],
144 7 : [69, 77, 93, 107, 111, 115, 121],
145 8 : [69, 79, 81, 89, 93, 99, 107, 119],
146 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
151 def stc(x,rho,message):
153 (mat,taille_suff) = trouve_H_hat(len(x),len(message),7)
154 x_b = x[:taille_suff]
155 (start,path) = forward(mat,x_b,message,lnm,rho)
156 return (x_b,backward(start,mat,x_b,message,lnm,path),mat)
176 def prod(H_hat,lnm,y):
177 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
180 V=[0 for _ in range(len(y))]
182 while i < lnm: # pour chaque ligne
183 V=[0 for _ in range(len(y))]
184 k = max([(i-h+1)*w,0])
186 for j in xrange(min([i+1,h])): #nbre de blocks presents sur la ligne i
187 for l in xrange(w): # pour chaque collone de H_hat
188 V[k] = bin(H_hat[l],h)[h-i-1+j+dec]
191 sol.append(np.dot(np.array(V),np.array(y)))
196 #print "dot",np.dot(H,y),H.shape
198 return sol#list(np.dot(H,y))
205 if x[i] % 2 != y[i]%2 :
215 def conversion(nombre, base, epsilon = 0.00001 ):
216 ''' Soit nombre écrit en base 10, le retourne en base base'''
217 if not 2 <= base <= 36:
218 raise ValueError, "La base doit être entre 2 et 36"
219 if not base == 2 and '.' in str(nombre):
220 raise ValueError, "La partie décimale n'est pas gérée pour les bases\
222 # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
224 abc = string.digits + string.letters
231 if '.' in str(nombre):
232 entier,decimal = int(str(nombre).split('.')[0]),\
233 float('.'+str(nombre).split('.')[1])
235 entier,decimal = int(str(nombre)),0
237 entier, rdigit = divmod( entier, base )
238 result = abc[rdigit] + result
239 flotante, decimalBin = 1./float(base),''
240 while flotante > epsilon :
241 if decimal >= flotante:
246 flotante = flotante/float(base)
247 if '1' in decimalBin :
248 reste = '.'+decimalBin
249 while reste[-1]=='0':
253 return sign + result + reste
257 '''Récupère le bit en position pos de X.
258 Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
259 On fera attention à ce que :
260 - on compte à partir du point,
261 - l'élément juste à gauche du point est en position 1,
262 - celui juste à droite est en position -1.'''
264 entier = conversion(X,2)
266 entier, decimal = entier.split('.')
272 entier = entier.replace('-','')
273 entier = entier.zfill(abs(pos))
274 decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]
276 return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])
280 '''Fixe le bit pos de X à la valeur y.
281 Le fonctionnement est similaire à getBit :
282 - on compte à partir du point,
283 - l'élément juste à gauche du point est en position 1,
284 - celui juste à droite est en position -1.'''
286 entier = conversion(X,2)
288 entier, decimal = entier.split('.')
291 entier = list(entier.zfill(abs(pos)))
292 decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
294 entier[len(entier)-pos]=str(int(y))
296 decimal[-pos-1] = str(int(y))
298 return int(''.join(entier),2)
301 for k in range(len(decimal)):
302 S += 1./2**(k+1)*int(decimal[k])
303 return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])
308 return ''.join('01'[(ai >> x) & 1] for x in xrange(7, -1, -1))
315 for j in list(a2b(i)):
322 return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
323 range(len(x)-1, -1, -1)))
325 def conv_list_bit(L):
327 for j in range(len(L)/8):
328 L2.append(chr(toDecimal("".join(L[j*8:(j+1)*8]))))
331 def Denary2Binary(n):
332 '''convert denary integer n to binary string bStr'''
334 if n < 0: raise ValueError, "must be a positive integer"
335 if n == 0: return '0'
337 bStr = str(n % 2) + bStr
342 def compute_filter_sobel(level,image):
344 level2= array(level2.getdata()).flatten()
349 level2_im=im.new('L',image.size)
350 level2_im.putdata(level2)
352 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 1)
353 cv.SetData(cv_im, level2_im.tostring())
354 dst16 = cv.CreateImage(cv.GetSize(cv_im), cv.IPL_DEPTH_16S, 1)
356 laplace = cv.Sobel(cv_im, dst16,1, 1,7)
358 dst8 = cv.CreateImage (cv.GetSize(cv_im), cv.IPL_DEPTH_8U, 1)
359 cv.ConvertScale(dst16,dst8)
360 processed=im.fromstring("L", cv.GetSize(dst8), dst8.tostring())
361 # cv.ShowImage ('canny', dst8)
368 def compute_list_bit_to_change(threshold,processed):
373 if (processed[l]>=threshold):
381 def compute_filter_canny(level,image,MsgLen):
383 bbs = BlumBlumShub();
388 level2= array(level2.getdata()).flatten()
393 level2_im=im.new('L',image.size)
394 level2_im.putdata(level2)
395 level2_im=im.merge("RGB",(level2_im,level2_im,level2_im))
396 # histo=level2_im.histogram()
397 mean=numpy.mean(level2)
398 std=numpy.std(level2)
400 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 3)
401 cv.SetData(cv_im, level2_im.tostring())
403 yuv = cv.CreateImage(cv.GetSize(cv_im), 8, 3)
404 gray = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
405 cv.CvtColor(cv_im, yuv, cv.CV_BGR2YCrCb)
406 cv.Split(yuv, gray, None, None, None)
410 canny = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
412 List_bit_to_change=set([])
417 cv.Canny(gray, canny, mean-1*std, mean+1*std,3) #avant 10 255
418 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
419 processed= array(processed.getdata()).flatten()
420 List3=set(compute_list_bit_to_change(100,processed))
422 cv.Canny(gray, canny, mean-1*std, mean+1*std,5) #avant 10 255
423 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
424 processed= array(processed.getdata()).flatten()
425 List5=set(compute_list_bit_to_change(100,processed))
427 cv.Canny(gray, canny, mean-1*std, mean+1*std,7) #avant 10 255
428 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
429 processed= array(processed.getdata()).flatten()
430 List7=set(compute_list_bit_to_change(100,processed))
433 nb_bit_embedded=max(2*MsgLen,int(len(List3)/MsgLen)*MsgLen)
434 print "nb_bit_embedded",nb_bit_embedded
435 AvailablePixel3=List3
436 AvailablePixel5=AvailablePixel3.union(List5)
437 AvailablePixel7=AvailablePixel5.union(List7)
440 if len(AvailablePixel3)>nb_bit_embedded:
442 WorkingPixel=AvailablePixel3
443 sub = bbs.sample(AvailablePixel3,nb_bit_embedded)
444 elif len(AvailablePixel5)>nb_bit_embedded:
446 WorkingPixel=AvailablePixel5
447 sub = AvailablePixel3.union(
448 bbs.sample(AvailablePixel5-AvailablePixel3,nb_bit_embedded-len(AvailablePixel3)))
450 elif len(AvailablePixel7)>nb_bit_embedded:
452 WorkingPixel=AvailablePixel7
453 sub = AvailablePixel5.union(
454 bbs.sample(AvailablePixel7-AvailablePixel5,nb_bit_embedded-len(AvailablePixel5)))
457 WorkingPixel=range(len(level2))
458 sub = range(len(level2))
461 print "avail P3",len(AvailablePixel3)
462 print "avail P5",len(AvailablePixel5)
463 print "avail P7",len(AvailablePixel7)
466 Weight=[0 for _ in sub]
470 if step>=1 and i in List3:
472 if step>=2 and i in List5 and Weight[l]==0:
474 if step>=3 and i in List7 and Weight[l]==0:
476 if step>=4 and Weight[l]==0:
480 List_bit_to_change=sub
492 def verifie(fileout,leng_msg,Message,):
495 dd2 = im.open(fileout)
496 dd2 = dd2.convert('RGB')
497 red2, green, blue = dd2.split()
500 [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2,leng_msg)
503 level2= array(level2.getdata()).flatten()
505 print "support2",len(List_bit_to_change2)
506 print "message2",len(Message)
507 print "weight2",len(Weight2)
509 alpha = float(len(List_bit_to_change2))/len(Message)
511 index = min(int(alpha),9)
515 4 : [81, 95, 107, 121],
516 5 : [75, 95, 97, 105, 117],
517 6 : [73, 83, 95, 103, 109, 123],
518 7 : [69, 77, 93, 107, 111, 115, 121],
519 8 : [69, 79, 81, 89, 93, 99, 107, 119],
520 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
527 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change2]
528 LL2=list(List_bit_to_change2)
531 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message2))])
532 print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
533 print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
535 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
538 # print "mesg",Message
539 # print "mesg2",Message2
548 bbs = BlumBlumShub();
553 while len(List_random)<len(Message2):
554 List_random.extend(Denary2Binary(bbs.next()))
558 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
559 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
560 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
562 #print "MessageDecoded2",MessageDecoded2
564 outIm = im.new("L",im.open("invader.png").size)
566 print "taille de l'image",l*h
567 print "taille des donneées",len(MessageDecoded2)
568 queue = [255 if x != 0 else 0 for x in MessageDecoded2]
569 queue = queue[len(queue)-l*h:]
571 outIm.save("apresSobel.png")
574 print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
575 for l in List_bit_to_change2:
576 if(val_mod2<leng_error*8):
577 list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
578 if(val_mod2==leng_error*8-1):
579 bin_leng2=''.join(list_msg)
580 coded_msg2=conv_list_bit(bin_leng2)
581 clear_msg2=coded_msg2
582 length_msg=int(clear_msg2)
584 if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
585 list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
586 if(len(list_msg)==leng_error*8):
587 pack=''.join(list_msg)
588 msg=conv_list_bit(pack)
589 decoded_msg=decoded_msg+msg
593 print decoded_msg#[0:20]
600 def mystego(filein, fileout,file_msg="invader"):
603 bbs = BlumBlumShub();
608 dd = dd.convert('RGB')
609 red, green, blue = dd.split()
612 #print type(level),level
618 message="Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete voila c'est la fin blablabla:-)"
620 message="Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela. Bon voici un test avec un message un peu plus long. Bon j'en rajoute pour voir. Ce que j'écris est très original... Bref, je suis un poete Salut christophe, arrives tu à lire ce message? normalement tu dois lire cela."
625 leng_msg=len(message)
626 print "taille du message en caracteres",leng_msg
627 message=message+((leng_msg+7)/8*8-leng_msg)*" "
628 leng_msg=len(message)
629 leng='%08d'%len(message)
632 leng_error=int(len_leng)
635 List_pack=a2b_list(leng_cor)
637 for i in range(leng_msg/8):
638 m=message[i*8:(i+1)*8]
640 m_bin=a2b_list(m_cor)
642 List_pack.extend(m_bin)
649 for c in [x if x==0 else 1 for x in im.open("invader.png").getdata()]:
652 leng_msg=len(message)
653 leng='%08d'%len(message)
655 leng_error=int(len_leng)
657 List_pack=a2b_list(leng_cor)
661 leng_msg=len(List_pack)
662 print "leng_msg",leng_msg
664 [List_bit_to_change,Weight]=compute_filter_canny(level,dd,leng_msg)
665 level= array(level.getdata()).flatten()
668 while len(List_random)<len(List_pack):
669 List_random.extend(Denary2Binary(bbs.next()))
673 #print List_bit_to_change
675 for l in List_bit_to_change :
676 Support += [getBit(level[l],bit_to_read) ]
681 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
683 #print "support",len(List_bit_to_change)
684 #print "message",Message
685 #print "weight",len(Weight)
687 #(x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
689 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
691 print "comparaison entre stc_message et message", len(Stc_message),len(Message)
694 #print "pourcentage modif",nbdif(x_b,Stc_message)
695 #print "taille Stc_message",len(Stc_message)
696 # Stc_message=Message
705 for l in List_bit_to_change:
706 if(size_mesg<len(Stc_message)):
707 b=getBit(level[l],bit_to_read)
708 if b!=Stc_message[size_mesg]:
710 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
713 #print 'size mesg',size_mesg
714 #print 'val mod',val_mod
715 #print 'len message',len(Message),len(List_pack)
719 zz3=im.new('L',dd.size)
721 #zz4=im.merge("RGB",(zz3, green, blue))
725 verifie(fileout,leng_msg,Message)
733 path_stego = '/home/couchot/rech/CCG12/canny/stc/exp/raphus/stego/'
734 path_cover = '/home/couchot/rech/BCG10/Oxford11/experiments/images/'
737 listing = [957, 108, 106, 29, 431, 924, 262, 477, 346, 809]
738 for infile in listing:
740 fi = path_cover+str(infile)+'.png'
741 fo = path_stego+str(infile)+'.png'
745 if __name__ == "__main__":