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))
432 #nb_bit_embedded=(512*512/10)+40
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
495 def mystego(filein, fileout):
498 bbs = BlumBlumShub();
503 dd = dd.convert('RGB')
504 red, green, blue = dd.split()
511 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:-)"
513 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."
518 leng_msg=len(message)
519 print "taille du message en caracteres",leng_msg
520 message=message+((leng_msg+7)/8*8-leng_msg)*" "
521 leng_msg=len(message)
522 leng='%08d'%len(message)
525 leng_error=int(len_leng)
528 List_pack=a2b_list(leng_cor)
530 for i in range(leng_msg/8):
531 m=message[i*8:(i+1)*8]
533 m_bin=a2b_list(m_cor)
535 List_pack.extend(m_bin)
542 for c in [x if x==0 else 1 for x in im.open("invader.png").getdata()]:
545 leng_msg=len(message)
546 leng='%08d'%len(message)
548 leng_error=int(len_leng)
550 List_pack=a2b_list(leng_cor)
554 leng_msg=len(List_pack)
556 [List_bit_to_change,Weight]=compute_filter_canny(level,dd,leng_msg)
557 level= array(level.getdata()).flatten()
560 while len(List_random)<len(List_bit_to_change):
561 List_random.extend(Denary2Binary(bbs.next()))
565 #print List_bit_to_change
567 for l in List_bit_to_change :
568 Support += [getBit(level[l],bit_to_read) ]
573 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
575 #print "support",len(List_bit_to_change)
576 #print "message",len(Message)
577 #print "weight",len(Weight)
579 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
581 #print "pourcentage modif",nbdif(x_b,Stc_message)
582 #print "taille Stc_message",len(Stc_message)
583 # Stc_message=Message
592 for l in List_bit_to_change:
593 if(size_mesg<len(Stc_message)):
594 b=getBit(level[l],bit_to_read)
595 if b!=Stc_message[size_mesg]:
597 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
600 #print 'size mesg',size_mesg
601 #print 'val mod',val_mod
602 #print 'len message',len(Message),len(List_pack)
606 zz3=im.new('L',dd.size)
608 #zz4=im.merge("RGB",(zz3, green, blue))
615 dd2 = im.open(fileout)
616 dd2 = dd2.convert('RGB')
617 red2, green, blue = dd2.split()
620 [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2,leng_msg)
623 level2= array(level2.getdata()).flatten()
625 print "support2",len(List_bit_to_change2)
626 print "message2",len(Message)
627 print "weight2",len(Weight2)
629 alpha = float(len(List_bit_to_change2))/len(Message)
631 index = min(int(alpha),9)
635 4 : [81, 95, 107, 121],
636 5 : [75, 95, 97, 105, 117],
637 6 : [73, 83, 95, 103, 109, 123],
638 7 : [69, 77, 93, 107, 111, 115, 121],
639 8 : [69, 79, 81, 89, 93, 99, 107, 119],
640 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
647 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change2]
648 LL1=list(List_bit_to_change);
649 LL2=list(List_bit_to_change2)
651 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message2))])
652 print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
653 print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
655 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
658 # print "mesg",Message
659 # print "mesg2",Message2
661 print equiv(Message,Message2)
670 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
671 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
672 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
674 print "MessageDecoded2",MessageDecoded2
675 print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
682 # for l in List_bit_to_change2:
683 # if(val_mod2<leng_error*8):
684 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
685 # if(val_mod2==leng_error*8-1):
686 # bin_leng2=''.join(list_msg)
687 # coded_msg2=conv_list_bit(bin_leng2)
688 # clear_msg2=coded_msg2
689 # length_msg=int(clear_msg2)
691 # if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
692 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
693 # if(len(list_msg)==leng_error*8):
694 # pack=''.join(list_msg)
695 # msg=conv_list_bit(pack)
696 # decoded_msg=decoded_msg+msg
701 print decoded_msg#[0:20]
702 print len(List_bit_to_change)
703 list_nb_bit.append(filein)
704 list_nb_bit.append(len(List_bit_to_change2))
709 #path_cover = '/localhome/couturie/ensemble/cover_bad_laplace/'
710 path_stego = '/home/couchot/rech/CCG12/canny/stc/exp/raphus/stego/'
711 path_cover = '/home/couchot/rech/BCG10/Oxford11/experiments/images/'
712 #path_stego = '/tmp/'
713 #path_stego = '/home/couturie/BossBase-1.0-canny/'
714 #listing = os.listdir(path_cover)
725 listing = [957, 108, 106, 29, 431, 924, 262, 477, 346, 809]
727 for infile in listing:
729 fi = path_cover+str(infile)+'.png'
730 fo = path_stego+str(infile)+'.png'
734 #f = open('histogram_boss_canny_100255', 'w')
735 #f = open('histogram', 'w')
736 #for item in list_nb_bit:
737 #f.write("%s\n" % item)