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
494 X=18532395500947174450709383384936679868383424444311
504 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:-)"
505 message=message[0:len(message)/1]
506 leng_msg=len(message)
507 message=message+((leng_msg+7)/8*8-leng_msg)*" "
508 leng_msg=len(message)
510 leng='%08d'%len(message)
516 leng_error=int(len_leng)
518 List_pack=a2b_list(leng_cor)
521 while len(List_random)<len(List_bit_to_change):
523 List_random.extend(Denary2Binary(X))
526 for i in range(leng_msg/8):
527 m=message[i*8:(i+1)*8]
529 m_bin=a2b_list(m_cor)
531 List_pack.extend(m_bin)
540 #List_bit_to_change = support
541 #print len(List_bit_to_change)
544 #print List_bit_to_change
545 Support=[getBit(level[l],bit_to_read) for l in List_bit_to_change]
546 #print len(List_pack)
550 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
552 print "support",len(List_bit_to_change)
553 print "message",len(Message)
554 print "weight",len(Weight)
556 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
558 print "pourcentage modif",nbdif(x_b,Stc_message)
559 print "taille Stc_message",len(Stc_message)
560 # Stc_message=Message
569 for l in List_bit_to_change:
570 if(size_mesg<len(Stc_message)):
571 b=getBit(level[l],bit_to_read)
572 if b!=Stc_message[size_mesg]:
574 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
577 print 'size mesg',size_mesg
578 print 'val mod',val_mod
579 print 'len message',len(Message),len(List_pack)
583 zz3=im.new('L',dd.size)
585 #zz4=im.merge("RGB",(zz3, green, blue))
592 # dd2 = im.open(fileout)
593 # dd2 = dd2.convert('RGB')
594 # red2, green, blue = dd2.split()
597 # [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2)
600 # level2= array(level2.getdata()).flatten()
602 # print "support2",len(List_bit_to_change2)
603 # print "message2",len(Message)
604 # print "weight2",len(Weight)
606 # alpha = float(len(List_bit_to_change2))/len(Message)
609 # index = min(int(alpha),9)
612 # 3 : [95, 101, 121],
613 # 4 : [81, 95, 107, 121],
614 # 5 : [75, 95, 97, 105, 117],
615 # 6 : [73, 83, 95, 103, 109, 123],
616 # 7 : [69, 77, 93, 107, 111, 115, 121],
617 # 8 : [69, 79, 81, 89, 93, 99, 107, 119],
618 # 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
625 # Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change]
626 # LL1=list(List_bit_to_change);
627 # LL2=list(List_bit_to_change2)
629 # print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message))])
630 # print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
631 # print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
633 # Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
636 # # print "mesg",Message
637 # # print "mesg2",Message2
639 # print equiv(Message,Message2)
648 # MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
649 # # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
650 # # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
652 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
659 # # for l in List_bit_to_change2:
660 # # if(val_mod2<leng_error*8):
661 # # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
662 # # if(val_mod2==leng_error*8-1):
663 # # bin_leng2=''.join(list_msg)
664 # # coded_msg2=conv_list_bit(bin_leng2)
665 # # clear_msg2=coded_msg2
666 # # length_msg=int(clear_msg2)
668 # # if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
669 # # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
670 # # if(len(list_msg)==leng_error*8):
671 # # pack=''.join(list_msg)
672 # # msg=conv_list_bit(pack)
673 # # decoded_msg=decoded_msg+msg
678 # print decoded_msg#[0:20]
679 # print len(List_bit_to_change)
680 # list_nb_bit.append(filein)
681 # list_nb_bit.append(len(List_bit_to_change))
686 #path_cover = '/localhome/couturie/ensemble/cover_bad_laplace/'
687 path_stego = '/localhome/couturie/ensemble/BossBase-1.0-canny_new/'
688 path_cover = '/localhome/couturie/ensemble/BossBase-1.0-cover/'
689 #path_stego = '/tmp/'
690 #path_stego = '/home/couturie/BossBase-1.0-canny/'
691 listing = os.listdir(path_cover)
697 #mystego(argv[1],argv[2])
702 for infile in listing:
704 if infile[0]==argv[1]:
705 print "current file is: " + infile, path_stego+infile
706 mystego(path_cover+infile,path_stego+infile)
709 #f = open('histogram_boss_canny_100255', 'w')
710 #f = open('histogram', 'w')
711 #for item in list_nb_bit:
712 # f.write("%s\n" % item)