26 acc = acc + 2**(n-i-1)
31 """Convertit un nombre en binaire"""
33 res = [0 for i in xrange(n)]
46 return 1 if a != b else 0
49 e1b,e2b = bin(e1,h),bin(e2,h)
50 d = dec([xorb(e1b[j],e2b[j]) for j in xrange(h)],h)
53 def lit(d,(indx,indy)):
62 def forward(H_hat,x,message,lnm,rho):
63 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
66 wght = [infinity for _ in xrange(int(2**h))]
68 newwght = [0 for _ in xrange(int(2**h))]
70 # rho= [1 for _ in xrange(len(x))]
73 while i < nbblock: # pour chaque bit du message
74 for j in xrange(w): # pour chaque colonne de H_hat
75 #print indx, "en entrant",wght
77 while k < int(2**h): # pour chaque ligne de H
78 w0 = wght[k] + x[indx]*rho[indx]
79 w1 = wght[xor(k,H_hat[j],h)] + (1-x[indx])*rho[indx]
85 newwght[k] = min(w0,w1)
88 wght = [t for t in newwght]
89 #print " apres calcul",wght
91 for j in xrange(int(2**(h-1))): # pour chaque colonne de H
92 wght[j] = wght[2*j + message[indm]]
93 wght = wght[:int(pow(2,h-1))] + [infinity for _ in xrange(int(pow(2,h)-pow(2,h-1)))]
96 start = np.argmin(wght)
100 def backward(start,H_hat,x,message,lnm,path):
101 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
102 indx,indm = len(x)-1,lnm-1
103 state = 2*start + message[indm]
105 # l'initialisation de state n'est pas optimale...
112 for j in l: # pour chaque colonne de H_hat
113 y[indx] = lit(path,(indx,state))
114 state = xor(state,y[indx]*H_hat[j],h)
116 state = 2*state + message[indm]
119 return [int(t) for t in y]
126 def trouve_H_hat(n,m,h):
130 index = min(int(alpha),9)
135 4 : [81, 95, 107, 121],
136 5 : [75, 95, 97, 105, 117],
137 6 : [73, 83, 95, 103, 109, 123],
138 7 : [69, 77, 93, 107, 111, 115, 121],
139 8 : [69, 79, 81, 89, 93, 99, 107, 119],
140 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
145 def stc(x,rho,message):
147 (mat,taille_suff) = trouve_H_hat(len(x),len(message),7)
148 x_b = x[:taille_suff]
149 (start,path) = forward(mat,x_b,message,lnm,rho)
150 return (x_b,backward(start,mat,x_b,message,lnm,path),mat)
170 def prod(H_hat,lnm,y):
171 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
174 V=[0 for _ in range(len(y))]
176 while i < lnm: # pour chaque ligne
177 V=[0 for _ in range(len(y))]
178 k = max([(i-h+1)*w,0])
180 for j in xrange(min([i+1,h])): #nbre de blocks presents sur la ligne i
181 for l in xrange(w): # pour chaque collone de H_hat
182 V[k] = bin(H_hat[l],h)[h-i-1+j+dec]
185 sol.append(np.dot(np.array(V),np.array(y)))
190 #print "dot",np.dot(H,y),H.shape
192 return sol#list(np.dot(H,y))
199 if x[i] % 2 != y[i]%2 :
209 def conversion(nombre, base, epsilon = 0.00001 ):
210 ''' Soit nombre écrit en base 10, le retourne en base base'''
211 if not 2 <= base <= 36:
212 raise ValueError, "La base doit être entre 2 et 36"
213 if not base == 2 and '.' in str(nombre):
214 raise ValueError, "La partie décimale n'est pas gérée pour les bases\
216 # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
218 abc = string.digits + string.letters
225 if '.' in str(nombre):
226 entier,decimal = int(str(nombre).split('.')[0]),\
227 float('.'+str(nombre).split('.')[1])
229 entier,decimal = int(str(nombre)),0
231 entier, rdigit = divmod( entier, base )
232 result = abc[rdigit] + result
233 flotante, decimalBin = 1./float(base),''
234 while flotante > epsilon :
235 if decimal >= flotante:
240 flotante = flotante/float(base)
241 if '1' in decimalBin :
242 reste = '.'+decimalBin
243 while reste[-1]=='0':
247 return sign + result + reste
251 '''Récupère le bit en position pos de X.
252 Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
253 On fera attention à ce que :
254 - on compte à partir du point,
255 - l'élément juste à gauche du point est en position 1,
256 - celui juste à droite est en position -1.'''
258 entier = conversion(X,2)
260 entier, decimal = entier.split('.')
266 entier = entier.replace('-','')
267 entier = entier.zfill(abs(pos))
268 decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]
270 return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])
274 '''Fixe le bit pos de X à la valeur y.
275 Le fonctionnement est similaire à getBit :
276 - on compte à partir du point,
277 - l'élément juste à gauche du point est en position 1,
278 - celui juste à droite est en position -1.'''
280 entier = conversion(X,2)
282 entier, decimal = entier.split('.')
285 entier = list(entier.zfill(abs(pos)))
286 decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
288 entier[len(entier)-pos]=str(int(y))
290 decimal[-pos-1] = str(int(y))
292 return int(''.join(entier),2)
295 for k in range(len(decimal)):
296 S += 1./2**(k+1)*int(decimal[k])
297 return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])
302 return ''.join('01'[(ai >> x) & 1] for x in xrange(7, -1, -1))
309 for j in list(a2b(i)):
316 return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
317 range(len(x)-1, -1, -1)))
319 def conv_list_bit(L):
321 for j in range(len(L)/8):
322 L2.append(chr(toDecimal("".join(L[j*8:(j+1)*8]))))
325 def Denary2Binary(n):
326 '''convert denary integer n to binary string bStr'''
328 if n < 0: raise ValueError, "must be a positive integer"
329 if n == 0: return '0'
331 bStr = str(n % 2) + bStr
336 def compute_filter_sobel(level,image):
338 level2= array(level2.getdata()).flatten()
343 level2_im=im.new('L',image.size)
344 level2_im.putdata(level2)
346 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 1)
347 cv.SetData(cv_im, level2_im.tostring())
348 dst16 = cv.CreateImage(cv.GetSize(cv_im), cv.IPL_DEPTH_16S, 1)
350 laplace = cv.Sobel(cv_im, dst16,1, 1,7)
352 dst8 = cv.CreateImage (cv.GetSize(cv_im), cv.IPL_DEPTH_8U, 1)
353 cv.ConvertScale(dst16,dst8)
354 processed=im.fromstring("L", cv.GetSize(dst8), dst8.tostring())
355 # cv.ShowImage ('canny', dst8)
362 def compute_list_bit_to_change(threshold,processed):
367 if (processed[l]>=threshold):
375 def compute_filter_canny(level,image):
377 level2= array(level2.getdata()).flatten()
382 level2_im=im.new('L',image.size)
383 level2_im.putdata(level2)
384 level2_im=im.merge("RGB",(level2_im,level2_im,level2_im))
385 # histo=level2_im.histogram()
386 mean=numpy.mean(level2)
387 std=numpy.std(level2)
389 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 3)
390 cv.SetData(cv_im, level2_im.tostring())
392 yuv = cv.CreateImage(cv.GetSize(cv_im), 8, 3)
393 gray = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
394 cv.CvtColor(cv_im, yuv, cv.CV_BGR2YCrCb)
395 cv.Split(yuv, gray, None, None, None)
399 canny = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
401 List_bit_to_change=set([])
406 cv.Canny(gray, canny, mean-1*std, mean+1*std,3) #avant 10 255
407 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
408 processed= array(processed.getdata()).flatten()
409 List3=set(compute_list_bit_to_change(100,processed))
411 cv.Canny(gray, canny, mean-1*std, mean+1*std,5) #avant 10 255
412 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
413 processed= array(processed.getdata()).flatten()
414 List5=set(compute_list_bit_to_change(100,processed))
416 cv.Canny(gray, canny, mean-1*std, mean+1*std,7) #avant 10 255
417 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
418 processed= array(processed.getdata()).flatten()
419 List7=set(compute_list_bit_to_change(100,processed))
421 nb_bit_embedded=(512*512/10)+40
422 AvailablePixel3=List3
423 AvailablePixel5=AvailablePixel3.union(List5)
424 AvailablePixel7=AvailablePixel5.union(List7)
425 if len(AvailablePixel3)>nb_bit_embedded:
427 WorkingPixel=AvailablePixel3
428 elif len(AvailablePixel5)>nb_bit_embedded:
430 WorkingPixel=AvailablePixel5
431 elif len(AvailablePixel7)>nb_bit_embedded:
433 WorkingPixel=AvailablePixel7
436 WorkingPixel=range(len(level2))
438 print "avail P3",len(AvailablePixel3)
439 print "avail P5",len(AvailablePixel5)
440 print "avail P7",len(AvailablePixel7)
442 print "size WorkingPixel",len(WorkingPixel)
443 Weight=[0 for _ in WorkingPixel]
446 for i in WorkingPixel:
447 if step>=1 and i in List3:
449 if step>=2 and i in List5 and Weight[l]==0:
451 if step>=3 and i in List7 and Weight[l]==0:
453 if step>=4 and Weight[l]==0:
460 List_bit_to_change=WorkingPixel
466 return [List_bit_to_change,Weight]
478 def mystego(filein, fileout):
480 dd = dd.convert('RGB')
481 red, green, blue = dd.split()
484 [List_bit_to_change,Weight]=compute_filter_canny(level,dd)
485 level= array(level.getdata()).flatten()
493 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
495 X=18532395500947174450709383384936679868383424444311
505 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:-)"
506 message=message[0:len(message)/1]
507 leng_msg=len(message)
508 message=message+((leng_msg+7)/8*8-leng_msg)*" "
509 leng_msg=len(message)
511 leng='%08d'%len(message)
517 leng_error=int(len_leng)
519 List_pack=a2b_list(leng_cor)
523 while len(List_random)<len(List_bit_to_change):
525 List_random.extend(Denary2Binary(X))
528 for i in range(leng_msg/8):
529 m=message[i*8:(i+1)*8]
531 m_bin=a2b_list(m_cor)
533 List_pack.extend(m_bin)
542 #List_bit_to_change = support
543 #print len(List_bit_to_change)
546 #print List_bit_to_change
547 Support=[getBit(level[l],bit_to_read) for l in List_bit_to_change]
548 #print len(List_pack)
552 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
554 print "support",len(List_bit_to_change)
555 print "message",len(Message)
556 print "weight",len(Weight)
558 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
560 print "pourcentage modif",nbdif(x_b,Stc_message)
561 print "taille Stc_message",len(Stc_message)
562 # Stc_message=Message
571 for l in List_bit_to_change:
572 if(size_mesg<len(Stc_message)):
573 b=getBit(level[l],bit_to_read)
574 if b!=Stc_message[size_mesg]:
576 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
579 print 'size mesg',size_mesg
580 print 'val mod',val_mod
581 print 'len message',len(Message),len(List_pack)
585 zz3=im.new('L',dd.size)
587 #zz4=im.merge("RGB",(zz3, green, blue))
594 dd2 = im.open(fileout)
595 dd2 = dd2.convert('RGB')
596 red2, green, blue = dd2.split()
599 [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2)
602 level2= array(level2.getdata()).flatten()
604 print "support2",len(List_bit_to_change2)
605 print "message2",len(Message)
606 print "weight2",len(Weight)
608 alpha = float(len(List_bit_to_change2))/len(Message)
611 index = min(int(alpha),9)
615 4 : [81, 95, 107, 121],
616 5 : [75, 95, 97, 105, 117],
617 6 : [73, 83, 95, 103, 109, 123],
618 7 : [69, 77, 93, 107, 111, 115, 121],
619 8 : [69, 79, 81, 89, 93, 99, 107, 119],
620 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
627 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change]
628 LL1=list(List_bit_to_change);
629 LL2=list(List_bit_to_change2)
631 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message))])
632 print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
633 print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
635 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
638 # print "mesg",Message
639 # print "mesg2",Message2
641 print equiv(Message,Message2)
650 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
651 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
652 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
654 print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
661 # for l in List_bit_to_change2:
662 # if(val_mod2<leng_error*8):
663 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
664 # if(val_mod2==leng_error*8-1):
665 # bin_leng2=''.join(list_msg)
666 # coded_msg2=conv_list_bit(bin_leng2)
667 # clear_msg2=coded_msg2
668 # length_msg=int(clear_msg2)
670 # if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
671 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
672 # if(len(list_msg)==leng_error*8):
673 # pack=''.join(list_msg)
674 # msg=conv_list_bit(pack)
675 # decoded_msg=decoded_msg+msg
680 print decoded_msg#[0:20]
681 print len(List_bit_to_change)
682 list_nb_bit.append(filein)
683 list_nb_bit.append(len(List_bit_to_change))
688 #path_cover = '/localhome/couturie/ensemble/cover_bad_laplace/'
689 path_stego = '/localhome/couturie/ensemble/BossBase-1.0-canny_new/'
690 path_cover = '/localhome/couturie/ensemble/BossBase-1.0-cover/'
691 #path_stego = '/tmp/'
692 #path_stego = '/home/couturie/BossBase-1.0-canny/'
693 #listing = os.listdir(path_cover)
699 mystego(argv[1],argv[2])
704 for infile in listing:
706 if infile[0]==argv[1]:
707 print "current file is: " + infile, path_stego+infile
708 mystego(path_cover+infile,path_stego+infile)
711 #f = open('histogram_boss_canny_100255', 'w')
712 #f = open('histogram', 'w')
713 #for item in list_nb_bit:
714 # f.write("%s\n" % item)