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)+40
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."
517 for c in [x if x==0 else 1 for x in im.open("invader.png").getdata()]:
523 leng_msg=len(message)
524 print "taille du message en caracteres",leng_msg
525 message=message+((leng_msg+7)/8*8-leng_msg)*" "
526 leng_msg=len(message)
527 leng='%08d'%len(message)
530 leng_error=int(len_leng)
533 List_pack=a2b_list(leng_cor)
535 for i in range(leng_msg/8):
536 m=message[i*8:(i+1)*8]
538 m_bin=a2b_list(m_cor)
540 List_pack.extend(m_bin)
543 leng_msg=len(List_pack)
545 [List_bit_to_change,Weight]=compute_filter_canny(level,dd,leng_msg)
546 level= array(level.getdata()).flatten()
549 while len(List_random)<len(List_bit_to_change):
550 List_random.extend(Denary2Binary(bbs.next()))
554 #print List_bit_to_change
556 for l in List_bit_to_change :
557 Support += [getBit(level[l],bit_to_read) ]
558 #print len(List_pack)
562 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
564 print "support",len(List_bit_to_change)
565 print "message",len(Message)
566 print "weight",len(Weight)
568 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
570 print "pourcentage modif",nbdif(x_b,Stc_message)
571 print "taille Stc_message",len(Stc_message)
572 # Stc_message=Message
581 for l in List_bit_to_change:
582 if(size_mesg<len(Stc_message)):
583 b=getBit(level[l],bit_to_read)
584 if b!=Stc_message[size_mesg]:
586 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
589 print 'size mesg',size_mesg
590 print 'val mod',val_mod
591 print 'len message',len(Message),len(List_pack)
595 zz3=im.new('L',dd.size)
597 #zz4=im.merge("RGB",(zz3, green, blue))
604 dd2 = im.open(fileout)
605 dd2 = dd2.convert('RGB')
606 red2, green, blue = dd2.split()
609 [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2,leng_msg)
612 level2= array(level2.getdata()).flatten()
614 print "support2",len(List_bit_to_change2)
615 print "message2",len(Message)
616 print "weight2",len(Weight2)
618 alpha = float(len(List_bit_to_change2))/len(Message)
620 index = min(int(alpha),9)
624 4 : [81, 95, 107, 121],
625 5 : [75, 95, 97, 105, 117],
626 6 : [73, 83, 95, 103, 109, 123],
627 7 : [69, 77, 93, 107, 111, 115, 121],
628 8 : [69, 79, 81, 89, 93, 99, 107, 119],
629 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
636 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change2]
637 LL1=list(List_bit_to_change);
638 LL2=list(List_bit_to_change2)
640 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message2))])
641 print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
642 print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
644 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
647 # print "mesg",Message
648 # print "mesg2",Message2
650 print equiv(Message,Message2)
659 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
660 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
661 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
663 print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
670 # for l in List_bit_to_change2:
671 # if(val_mod2<leng_error*8):
672 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
673 # if(val_mod2==leng_error*8-1):
674 # bin_leng2=''.join(list_msg)
675 # coded_msg2=conv_list_bit(bin_leng2)
676 # clear_msg2=coded_msg2
677 # length_msg=int(clear_msg2)
679 # if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
680 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
681 # if(len(list_msg)==leng_error*8):
682 # pack=''.join(list_msg)
683 # msg=conv_list_bit(pack)
684 # decoded_msg=decoded_msg+msg
689 print decoded_msg#[0:20]
690 print len(List_bit_to_change)
691 list_nb_bit.append(filein)
692 list_nb_bit.append(len(List_bit_to_change2))
697 #path_cover = '/localhome/couturie/ensemble/cover_bad_laplace/'
698 path_stego = '/localhome/couturie/ensemble/BossBase-1.0-canny_new/'
699 path_cover = '/localhome/couturie/ensemble/BossBase-1.0-cover/'
700 #path_stego = '/tmp/'
701 #path_stego = '/home/couturie/BossBase-1.0-canny/'
702 #listing = os.listdir(path_cover)
708 mystego(argv[1],argv[2])
713 for infile in listing:
715 if infile[0]==argv[1]:
716 print "current file is: " + infile, path_stego+infile
717 mystego(path_cover+infile,path_stego+infile)
720 #f = open('histogram_boss_canny_100255', 'w')
721 #f = open('histogram', 'w')
722 #for item in list_nb_bit:
723 # f.write("%s\n" % item)