28 acc = acc + 2**(n-i-1)
33 """Convertit un nombre en binaire"""
35 res = [0 for i in xrange(n)]
48 return 1 if a != b else 0
51 e1b,e2b = bin(e1,h),bin(e2,h)
52 d = dec([xorb(e1b[j],e2b[j]) for j in xrange(h)],h)
55 def lit(d,(indx,indy)):
64 def forward(H_hat,x,message,lnm,rho):
65 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
68 wght = [infinity for _ in xrange(int(2**h))]
70 newwght = [0 for _ in xrange(int(2**h))]
72 # rho= [1 for _ in xrange(len(x))]
75 while i < nbblock: # pour chaque bit du message
76 for j in xrange(w): # pour chaque colonne de H_hat
77 #print indx, "en entrant",wght
79 while k < int(2**h): # pour chaque ligne de H
80 w0 = wght[k] + x[indx]*rho[indx]
81 w1 = wght[xor(k,H_hat[j],h)] + (1-x[indx])*rho[indx]
87 newwght[k] = min(w0,w1)
90 wght = [t for t in newwght]
91 #print " apres calcul",wght
93 for j in xrange(int(2**(h-1))): # pour chaque colonne de H
94 wght[j] = wght[2*j + message[indm]]
95 wght = wght[:int(pow(2,h-1))] + [infinity for _ in xrange(int(pow(2,h)-pow(2,h-1)))]
98 start = np.argmin(wght)
102 def backward(start,H_hat,x,message,lnm,path):
103 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
104 indx,indm = len(x)-1,lnm-1
105 state = 2*start + message[indm]
107 # l'initialisation de state n'est pas optimale...
114 for j in l: # pour chaque colonne de H_hat
115 y[indx] = lit(path,(indx,state))
116 state = xor(state,y[indx]*H_hat[j],h)
118 state = 2*state + message[indm]
121 return [int(t) for t in y]
128 def trouve_H_hat(n,m,h):
132 index = min(int(alpha),9)
137 4 : [81, 95, 107, 121],
138 5 : [75, 95, 97, 105, 117],
139 6 : [73, 83, 95, 103, 109, 123],
140 7 : [69, 77, 93, 107, 111, 115, 121],
141 8 : [69, 79, 81, 89, 93, 99, 107, 119],
142 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
147 def stc(x,rho,message):
149 (mat,taille_suff) = trouve_H_hat(len(x),len(message),7)
150 x_b = x[:taille_suff]
151 (start,path) = forward(mat,x_b,message,lnm,rho)
152 return (x_b,backward(start,mat,x_b,message,lnm,path),mat)
172 def prod(H_hat,lnm,y):
173 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
176 V=[0 for _ in range(len(y))]
178 while i < lnm: # pour chaque ligne
179 V=[0 for _ in range(len(y))]
180 k = max([(i-h+1)*w,0])
182 for j in xrange(min([i+1,h])): #nbre de blocks presents sur la ligne i
183 for l in xrange(w): # pour chaque collone de H_hat
184 V[k] = bin(H_hat[l],h)[h-i-1+j+dec]
187 sol.append(np.dot(np.array(V),np.array(y)))
192 #print "dot",np.dot(H,y),H.shape
194 return sol#list(np.dot(H,y))
201 if x[i] % 2 != y[i]%2 :
211 def conversion(nombre, base, epsilon = 0.00001 ):
212 ''' Soit nombre écrit en base 10, le retourne en base base'''
213 if not 2 <= base <= 36:
214 raise ValueError, "La base doit être entre 2 et 36"
215 if not base == 2 and '.' in str(nombre):
216 raise ValueError, "La partie décimale n'est pas gérée pour les bases\
218 # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
220 abc = string.digits + string.letters
227 if '.' in str(nombre):
228 entier,decimal = int(str(nombre).split('.')[0]),\
229 float('.'+str(nombre).split('.')[1])
231 entier,decimal = int(str(nombre)),0
233 entier, rdigit = divmod( entier, base )
234 result = abc[rdigit] + result
235 flotante, decimalBin = 1./float(base),''
236 while flotante > epsilon :
237 if decimal >= flotante:
242 flotante = flotante/float(base)
243 if '1' in decimalBin :
244 reste = '.'+decimalBin
245 while reste[-1]=='0':
249 return sign + result + reste
253 '''Récupère le bit en position pos de X.
254 Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
255 On fera attention à ce que :
256 - on compte à partir du point,
257 - l'élément juste à gauche du point est en position 1,
258 - celui juste à droite est en position -1.'''
260 entier = conversion(X,2)
262 entier, decimal = entier.split('.')
268 entier = entier.replace('-','')
269 entier = entier.zfill(abs(pos))
270 decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]
272 return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])
276 '''Fixe le bit pos de X à la valeur y.
277 Le fonctionnement est similaire à getBit :
278 - on compte à partir du point,
279 - l'élément juste à gauche du point est en position 1,
280 - celui juste à droite est en position -1.'''
282 entier = conversion(X,2)
284 entier, decimal = entier.split('.')
287 entier = list(entier.zfill(abs(pos)))
288 decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
290 entier[len(entier)-pos]=str(int(y))
292 decimal[-pos-1] = str(int(y))
294 return int(''.join(entier),2)
297 for k in range(len(decimal)):
298 S += 1./2**(k+1)*int(decimal[k])
299 return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])
304 return ''.join('01'[(ai >> x) & 1] for x in xrange(7, -1, -1))
311 for j in list(a2b(i)):
318 return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
319 range(len(x)-1, -1, -1)))
321 def conv_list_bit(L):
323 for j in range(len(L)/8):
324 L2.append(chr(toDecimal("".join(L[j*8:(j+1)*8]))))
327 def Denary2Binary(n):
328 '''convert denary integer n to binary string bStr'''
330 if n < 0: raise ValueError, "must be a positive integer"
331 if n == 0: return '0'
333 bStr = str(n % 2) + bStr
338 def compute_filter_sobel(level,image):
340 level2= array(level2.getdata()).flatten()
345 level2_im=im.new('L',image.size)
346 level2_im.putdata(level2)
348 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 1)
349 cv.SetData(cv_im, level2_im.tostring())
350 dst16 = cv.CreateImage(cv.GetSize(cv_im), cv.IPL_DEPTH_16S, 1)
352 laplace = cv.Sobel(cv_im, dst16,1, 1,7)
354 dst8 = cv.CreateImage (cv.GetSize(cv_im), cv.IPL_DEPTH_8U, 1)
355 cv.ConvertScale(dst16,dst8)
356 processed=im.fromstring("L", cv.GetSize(dst8), dst8.tostring())
357 # cv.ShowImage ('canny', dst8)
364 def compute_list_bit_to_change(threshold,processed):
369 if (processed[l]>=threshold):
377 def compute_filter_canny(level,image,MsgLen):
379 bbs = BlumBlumShub();
380 bbs.setN(18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959)
381 bbs.setSeed(18532395500947174450709383384936679868383424444311)
384 level2= array(level2.getdata()).flatten()
389 level2_im=im.new('L',image.size)
390 level2_im.putdata(level2)
391 level2_im=im.merge("RGB",(level2_im,level2_im,level2_im))
392 # histo=level2_im.histogram()
393 mean=numpy.mean(level2)
394 std=numpy.std(level2)
396 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 3)
397 cv.SetData(cv_im, level2_im.tostring())
399 yuv = cv.CreateImage(cv.GetSize(cv_im), 8, 3)
400 gray = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
401 cv.CvtColor(cv_im, yuv, cv.CV_BGR2YCrCb)
402 cv.Split(yuv, gray, None, None, None)
406 canny = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
408 List_bit_to_change=set([])
413 cv.Canny(gray, canny, mean-1*std, mean+1*std,3) #avant 10 255
414 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
415 processed= array(processed.getdata()).flatten()
416 List3=set(compute_list_bit_to_change(100,processed))
418 cv.Canny(gray, canny, mean-1*std, mean+1*std,5) #avant 10 255
419 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
420 processed= array(processed.getdata()).flatten()
421 List5=set(compute_list_bit_to_change(100,processed))
423 cv.Canny(gray, canny, mean-1*std, mean+1*std,7) #avant 10 255
424 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
425 processed= array(processed.getdata()).flatten()
426 List7=set(compute_list_bit_to_change(100,processed))
428 #nb_bit_embedded=(512*512/10)+40
429 nb_bit_embedded=max(2*MsgLen,int(len(List3)/MsgLen)*MsgLen)+40
430 print "nb_bit_embedded",nb_bit_embedded
431 AvailablePixel3=List3
432 AvailablePixel5=AvailablePixel3.union(List5)
433 AvailablePixel7=AvailablePixel5.union(List7)
436 if len(AvailablePixel3)>nb_bit_embedded:
438 WorkingPixel=AvailablePixel3
439 sub = bbs.sample(AvailablePixel3,nb_bit_embedded)
440 elif len(AvailablePixel5)>nb_bit_embedded:
442 WorkingPixel=AvailablePixel5
443 sub = AvailablePixel3.union(
444 bbs.sample(AvailablePixel5-AvailablePixel3,nb_bit_embedded-len(AvailablePixel3)))
446 elif len(AvailablePixel7)>nb_bit_embedded:
448 WorkingPixel=AvailablePixel7
449 sub = AvailablePixel5.union(
450 bbs.sample(AvailablePixel7-AvailablePixel5,nb_bit_embedded-len(AvailablePixel5)))
453 WorkingPixel=range(len(level2))
454 sub = range(len(level2))
457 print "avail P3",len(AvailablePixel3)
458 print "avail P5",len(AvailablePixel5)
459 print "avail P7",len(AvailablePixel7)
462 Weight=[0 for _ in sub]
466 if step>=1 and i in List3:
468 if step>=2 and i in List5 and Weight[l]==0:
470 if step>=3 and i in List7 and Weight[l]==0:
472 if step>=4 and Weight[l]==0:
479 List_bit_to_change=sub
497 def mystego(filein, fileout):
499 dd = dd.convert('RGB')
500 red, green, blue = dd.split()
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:-)"
507 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."
510 message=message[0:len(message)/1]
511 leng_msg=len(message)
512 message=message+((leng_msg+7)/8*8-leng_msg)*" "
513 leng_msg=len(message)
515 leng='%08d'%len(message)
521 leng_error=int(len_leng)
523 List_pack=a2b_list(leng_cor)
529 [List_bit_to_change,Weight]=compute_filter_canny(level,dd,leng_msg)
530 level= array(level.getdata()).flatten()
538 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
540 X=18532395500947174450709383384936679868383424444311
551 while len(List_random)<len(List_bit_to_change):
553 List_random.extend(Denary2Binary(X))
556 for i in range(leng_msg/8):
557 m=message[i*8:(i+1)*8]
559 m_bin=a2b_list(m_cor)
561 List_pack.extend(m_bin)
570 #List_bit_to_change = support
571 #print len(List_bit_to_change)
574 #print List_bit_to_change
575 Support=[getBit(level[l],bit_to_read) for l in List_bit_to_change]
576 #print len(List_pack)
580 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
582 print "support",len(List_bit_to_change)
583 print "message",len(Message)
584 print "weight",len(Weight)
586 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
588 print "pourcentage modif",nbdif(x_b,Stc_message)
589 print "taille Stc_message",len(Stc_message)
590 # Stc_message=Message
599 for l in List_bit_to_change:
600 if(size_mesg<len(Stc_message)):
601 b=getBit(level[l],bit_to_read)
602 if b!=Stc_message[size_mesg]:
604 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
607 print 'size mesg',size_mesg
608 print 'val mod',val_mod
609 print 'len message',len(Message),len(List_pack)
613 zz3=im.new('L',dd.size)
615 #zz4=im.merge("RGB",(zz3, green, blue))
622 dd2 = im.open(fileout)
623 dd2 = dd2.convert('RGB')
624 red2, green, blue = dd2.split()
627 [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2,len(Message))
630 level2= array(level2.getdata()).flatten()
632 print "support2",len(List_bit_to_change2)
633 print "message2",len(Message)
634 print "weight2",len(Weight2)
636 alpha = float(len(List_bit_to_change2))/len(Message)
639 index = min(int(alpha),9)
643 4 : [81, 95, 107, 121],
644 5 : [75, 95, 97, 105, 117],
645 6 : [73, 83, 95, 103, 109, 123],
646 7 : [69, 77, 93, 107, 111, 115, 121],
647 8 : [69, 79, 81, 89, 93, 99, 107, 119],
648 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
655 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change2]
656 LL1=list(List_bit_to_change);
657 LL2=list(List_bit_to_change2)
659 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message2))])
660 print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
661 print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
663 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
666 # print "mesg",Message
667 # print "mesg2",Message2
669 print equiv(Message,Message2)
678 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
679 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
680 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
682 print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
689 # for l in List_bit_to_change2:
690 # if(val_mod2<leng_error*8):
691 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
692 # if(val_mod2==leng_error*8-1):
693 # bin_leng2=''.join(list_msg)
694 # coded_msg2=conv_list_bit(bin_leng2)
695 # clear_msg2=coded_msg2
696 # length_msg=int(clear_msg2)
698 # if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
699 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
700 # if(len(list_msg)==leng_error*8):
701 # pack=''.join(list_msg)
702 # msg=conv_list_bit(pack)
703 # decoded_msg=decoded_msg+msg
708 print decoded_msg#[0:20]
709 print len(List_bit_to_change)
710 list_nb_bit.append(filein)
711 list_nb_bit.append(len(List_bit_to_change))
716 #path_cover = '/localhome/couturie/ensemble/cover_bad_laplace/'
717 path_stego = '/localhome/couturie/ensemble/BossBase-1.0-canny_new/'
718 path_cover = '/localhome/couturie/ensemble/BossBase-1.0-cover/'
719 #path_stego = '/tmp/'
720 #path_stego = '/home/couturie/BossBase-1.0-canny/'
721 #listing = os.listdir(path_cover)
727 mystego(argv[1],argv[2])
732 for infile in listing:
734 if infile[0]==argv[1]:
735 print "current file is: " + infile, path_stego+infile
736 mystego(path_cover+infile,path_stego+infile)
739 #f = open('histogram_boss_canny_100255', 'w')
740 #f = open('histogram', 'w')
741 #for item in list_nb_bit:
742 # f.write("%s\n" % item)