16 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
18 X=18532395500947174450709383384936679868383424444311
34 acc = acc + 2**(n-i-1)
39 """Convertit un nombre en binaire"""
41 res = [0 for i in xrange(n)]
54 return 1 if a != b else 0
57 e1b,e2b = bin(e1,h),bin(e2,h)
58 d = dec([xorb(e1b[j],e2b[j]) for j in xrange(h)],h)
61 def lit(d,(indx,indy)):
70 def forward(H_hat,x,message,lnm,rho):
71 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
74 wght = [infinity for _ in xrange(int(2**h))]
76 newwght = [0 for _ in xrange(int(2**h))]
78 # rho= [1 for _ in xrange(len(x))]
81 while i < nbblock: # pour chaque bit du message
82 for j in xrange(w): # pour chaque colonne de H_hat
83 #print indx, "en entrant",wght
85 while k < int(2**h): # pour chaque ligne de H
86 w0 = wght[k] + x[indx]*rho[indx]
87 w1 = wght[xor(k,H_hat[j],h)] + (1-x[indx])*rho[indx]
93 newwght[k] = min(w0,w1)
96 wght = [t for t in newwght]
97 #print " apres calcul",wght
99 for j in xrange(int(2**(h-1))): # pour chaque colonne de H
100 wght[j] = wght[2*j + message[indm]]
101 wght = wght[:int(pow(2,h-1))] + [infinity for _ in xrange(int(pow(2,h)-pow(2,h-1)))]
104 start = np.argmin(wght)
108 def backward(start,H_hat,x,message,lnm,path):
109 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
110 indx,indm = len(x)-1,lnm-1
111 state = 2*start + message[indm]
113 # l'initialisation de state n'est pas optimale...
120 for j in l: # pour chaque colonne de H_hat
121 y[indx] = lit(path,(indx,state))
122 state = xor(state,y[indx]*H_hat[j],h)
124 state = 2*state + message[indm]
127 return [int(t) for t in y]
134 def trouve_H_hat(n,m,h):
138 index = min(int(alpha),9)
143 4 : [81, 95, 107, 121],
144 5 : [75, 95, 97, 105, 117],
145 6 : [73, 83, 95, 103, 109, 123],
146 7 : [69, 77, 93, 107, 111, 115, 121],
147 8 : [69, 79, 81, 89, 93, 99, 107, 119],
148 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
153 def stc(x,rho,message):
155 (mat,taille_suff) = trouve_H_hat(len(x),len(message),7)
156 x_b = x[:taille_suff]
157 (start,path) = forward(mat,x_b,message,lnm,rho)
158 return (x_b,backward(start,mat,x_b,message,lnm,path),mat)
178 def prod(H_hat,lnm,y):
179 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
182 V=[0 for _ in range(len(y))]
184 while i < lnm: # pour chaque ligne
185 V=[0 for _ in range(len(y))]
186 k = max([(i-h+1)*w,0])
188 for j in xrange(min([i+1,h])): #nbre de blocks presents sur la ligne i
189 for l in xrange(w): # pour chaque collone de H_hat
190 V[k] = bin(H_hat[l],h)[h-i-1+j+dec]
193 sol.append(np.dot(np.array(V),np.array(y)))
198 #print "dot",np.dot(H,y),H.shape
200 return sol#list(np.dot(H,y))
207 if x[i] % 2 != y[i]%2 :
217 def conversion(nombre, base, epsilon = 0.00001 ):
218 ''' Soit nombre écrit en base 10, le retourne en base base'''
219 if not 2 <= base <= 36:
220 raise ValueError, "La base doit être entre 2 et 36"
221 if not base == 2 and '.' in str(nombre):
222 raise ValueError, "La partie décimale n'est pas gérée pour les bases\
224 # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
226 abc = string.digits + string.letters
233 if '.' in str(nombre):
234 entier,decimal = int(str(nombre).split('.')[0]),\
235 float('.'+str(nombre).split('.')[1])
237 entier,decimal = int(str(nombre)),0
239 entier, rdigit = divmod( entier, base )
240 result = abc[rdigit] + result
241 flotante, decimalBin = 1./float(base),''
242 while flotante > epsilon :
243 if decimal >= flotante:
248 flotante = flotante/float(base)
249 if '1' in decimalBin :
250 reste = '.'+decimalBin
251 while reste[-1]=='0':
255 return sign + result + reste
259 '''Récupère le bit en position pos de X.
260 Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
261 On fera attention à ce que :
262 - on compte à partir du point,
263 - l'élément juste à gauche du point est en position 1,
264 - celui juste à droite est en position -1.'''
266 entier = conversion(X,2)
268 entier, decimal = entier.split('.')
274 entier = entier.replace('-','')
275 entier = entier.zfill(abs(pos))
276 decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]
278 return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])
282 '''Fixe le bit pos de X à la valeur y.
283 Le fonctionnement est similaire à getBit :
284 - on compte à partir du point,
285 - l'élément juste à gauche du point est en position 1,
286 - celui juste à droite est en position -1.'''
288 entier = conversion(X,2)
290 entier, decimal = entier.split('.')
293 entier = list(entier.zfill(abs(pos)))
294 decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
296 entier[len(entier)-pos]=str(int(y))
298 decimal[-pos-1] = str(int(y))
300 return int(''.join(entier),2)
303 for k in range(len(decimal)):
304 S += 1./2**(k+1)*int(decimal[k])
305 return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])
310 return ''.join('01'[(ai >> x) & 1] for x in xrange(7, -1, -1))
317 for j in list(a2b(i)):
324 return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
325 range(len(x)-1, -1, -1)))
327 def conv_list_bit(L):
329 for j in range(len(L)/8):
330 L2.append(chr(toDecimal("".join(L[j*8:(j+1)*8]))))
333 def Denary2Binary(n):
334 '''convert denary integer n to binary string bStr'''
336 if n < 0: raise ValueError, "must be a positive integer"
337 if n == 0: return '0'
339 bStr = str(n % 2) + bStr
344 def compute_filter_sobel(level,image):
346 level2= array(level2.getdata()).flatten()
351 level2_im=im.new('L',image.size)
352 level2_im.putdata(level2)
354 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 1)
355 cv.SetData(cv_im, level2_im.tostring())
356 dst16 = cv.CreateImage(cv.GetSize(cv_im), cv.IPL_DEPTH_16S, 1)
358 laplace = cv.Sobel(cv_im, dst16,1, 1,7)
360 dst8 = cv.CreateImage (cv.GetSize(cv_im), cv.IPL_DEPTH_8U, 1)
361 cv.ConvertScale(dst16,dst8)
362 processed=im.fromstring("L", cv.GetSize(dst8), dst8.tostring())
363 # cv.ShowImage ('canny', dst8)
370 def compute_list_bit_to_change(threshold,processed):
375 if (processed[l]>=threshold):
383 def compute_filter_canny(level,image,MsgLen):
385 bbs = BlumBlumShub();
390 level2= array(level2.getdata()).flatten()
395 level2_im=im.new('L',image.size)
396 level2_im.putdata(level2)
397 level2_im=im.merge("RGB",(level2_im,level2_im,level2_im))
398 # histo=level2_im.histogram()
399 mean=numpy.mean(level2)
400 std=numpy.std(level2)
402 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 3)
403 cv.SetData(cv_im, level2_im.tostring())
405 yuv = cv.CreateImage(cv.GetSize(cv_im), 8, 3)
406 gray = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
407 cv.CvtColor(cv_im, yuv, cv.CV_BGR2YCrCb)
408 cv.Split(yuv, gray, None, None, None)
412 canny = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
414 List_bit_to_change=set([])
419 cv.Canny(gray, canny, mean-1*std, mean+1*std,3) #avant 10 255
420 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
421 processed= array(processed.getdata()).flatten()
422 List3=set(compute_list_bit_to_change(100,processed))
424 cv.Canny(gray, canny, mean-1*std, mean+1*std,5) #avant 10 255
425 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
426 processed= array(processed.getdata()).flatten()
427 List5=set(compute_list_bit_to_change(100,processed))
429 cv.Canny(gray, canny, mean-1*std, mean+1*std,7) #avant 10 255
430 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
431 processed= array(processed.getdata()).flatten()
432 List7=set(compute_list_bit_to_change(100,processed))
434 #nb_bit_embedded=(512*512/10)+40
435 nb_bit_embedded=max(2*MsgLen,int(len(List3)/MsgLen)*MsgLen)+40
436 print "nb_bit_embedded",nb_bit_embedded
437 AvailablePixel3=List3
438 AvailablePixel5=AvailablePixel3.union(List5)
439 AvailablePixel7=AvailablePixel5.union(List7)
442 if len(AvailablePixel3)>nb_bit_embedded:
444 WorkingPixel=AvailablePixel3
445 sub = bbs.sample(AvailablePixel3,nb_bit_embedded)
446 elif len(AvailablePixel5)>nb_bit_embedded:
448 WorkingPixel=AvailablePixel5
449 sub = AvailablePixel3.union(
450 bbs.sample(AvailablePixel5-AvailablePixel3,nb_bit_embedded-len(AvailablePixel3)))
452 elif len(AvailablePixel7)>nb_bit_embedded:
454 WorkingPixel=AvailablePixel7
455 sub = AvailablePixel5.union(
456 bbs.sample(AvailablePixel7-AvailablePixel5,nb_bit_embedded-len(AvailablePixel5)))
459 WorkingPixel=range(len(level2))
460 sub = range(len(level2))
463 print "avail P3",len(AvailablePixel3)
464 print "avail P5",len(AvailablePixel5)
465 print "avail P7",len(AvailablePixel7)
468 Weight=[0 for _ in sub]
472 if step>=1 and i in List3:
474 if step>=2 and i in List5 and Weight[l]==0:
476 if step>=3 and i in List7 and Weight[l]==0:
478 if step>=4 and Weight[l]==0:
485 List_bit_to_change=sub
503 def mystego(filein, fileout):
505 bbs = BlumBlumShub();
512 dd = dd.convert('RGB')
513 red, green, blue = dd.split()
518 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:-)"
520 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."
524 for c in [x if x==0 else 1 for x in im.open("invader.png").getdata()]:
530 leng_msg=len(message)
536 while len(List_random)<len(List_bit_to_change):
537 List_random.extend(Denary2Binary(bbs.next()))
540 for i in range(leng_msg/8):
541 m=message[i*8:(i+1)*8]
543 m_bin=a2b_list(m_cor)
545 List_pack.extend(m_bin)
554 #List_bit_to_change = support
555 #print len(List_bit_to_change)
558 #print List_bit_to_change
559 Support=[getBit(level[l],bit_to_read) for l in List_bit_to_change]
560 #print len(List_pack)
564 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
566 print "support",len(List_bit_to_change)
567 print "message",len(Message)
568 print "weight",len(Weight)
570 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
572 print "pourcentage modif",nbdif(x_b,Stc_message)
573 print "taille Stc_message",len(Stc_message)
574 # Stc_message=Message
583 for l in List_bit_to_change:
584 if(size_mesg<len(Stc_message)):
585 b=getBit(level[l],bit_to_read)
586 if b!=Stc_message[size_mesg]:
588 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
591 print 'size mesg',size_mesg
592 print 'val mod',val_mod
593 print 'len message',len(Message),len(List_pack)
597 zz3=im.new('L',dd.size)
599 #zz4=im.merge("RGB",(zz3, green, blue))
606 dd2 = im.open(fileout)
607 dd2 = dd2.convert('RGB')
608 red2, green, blue = dd2.split()
611 [List_bit_to_change2,Weight2]=compute_filter_canny(level2,dd2,leng_msg)
614 level2= array(level2.getdata()).flatten()
616 print "support2",len(List_bit_to_change2)
617 print "message2",len(Message)
618 print "weight2",len(Weight2)
620 alpha = float(len(List_bit_to_change2))/len(Message)
622 index = min(int(alpha),9)
626 4 : [81, 95, 107, 121],
627 5 : [75, 95, 97, 105, 117],
628 6 : [73, 83, 95, 103, 109, 123],
629 7 : [69, 77, 93, 107, 111, 115, 121],
630 8 : [69, 79, 81, 89, 93, 99, 107, 119],
631 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
638 Stc_message2=[getBit(level2[l],bit_to_read) for l in List_bit_to_change2]
639 LL1=list(List_bit_to_change);
640 LL2=list(List_bit_to_change2)
642 print "Level",max([level2[l]-level[l] for l in xrange(len(Stc_message2))])
643 print "List bit to change",max([LL2[l]-LL1[l] for l in xrange(len(Stc_message))])
644 print "Stc message", max([Stc_message[l]-Stc_message2[l] for l in xrange(len(Stc_message))])
646 Message2 = [x%2 for x in prod(H_hat2,len(Message),Stc_message2)]
649 # print "mesg",Message
650 # print "mesg2",Message2
652 print equiv(Message,Message2)
661 MessageDecoded2=[(int(Message2[l])^int(List_random[l])) for l in xrange(len(Message2))]
662 # print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)]))
663 # print int(conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(leng_error*8)])))
665 print conv_list_bit(''.join([`MessageDecoded2[i]` for i in xrange(len(Message2))]))
672 # for l in List_bit_to_change2:
673 # if(val_mod2<leng_error*8):
674 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
675 # if(val_mod2==leng_error*8-1):
676 # bin_leng2=''.join(list_msg)
677 # coded_msg2=conv_list_bit(bin_leng2)
678 # clear_msg2=coded_msg2
679 # length_msg=int(clear_msg2)
681 # if(val_mod2>=leng_error*8 and val_mod2<leng_error*8+length_msg*leng_error):
682 # list_msg.append(`getBit(level2[l],bit_to_read)^int(List_random[val_mod2])`)
683 # if(len(list_msg)==leng_error*8):
684 # pack=''.join(list_msg)
685 # msg=conv_list_bit(pack)
686 # decoded_msg=decoded_msg+msg
691 print decoded_msg#[0:20]
692 print len(List_bit_to_change)
693 list_nb_bit.append(filein)
694 list_nb_bit.append(len(List_bit_to_change))
699 #path_cover = '/localhome/couturie/ensemble/cover_bad_laplace/'
700 path_stego = '/localhome/couturie/ensemble/BossBase-1.0-canny_new/'
701 path_cover = '/localhome/couturie/ensemble/BossBase-1.0-cover/'
702 #path_stego = '/tmp/'
703 #path_stego = '/home/couturie/BossBase-1.0-canny/'
704 #listing = os.listdir(path_cover)
710 mystego(argv[1],argv[2])
715 for infile in listing:
717 if infile[0]==argv[1]:
718 print "current file is: " + infile, path_stego+infile
719 mystego(path_cover+infile,path_stego+infile)
722 #f = open('histogram_boss_canny_100255', 'w')
723 #f = open('histogram', 'w')
724 #for item in list_nb_bit:
725 # f.write("%s\n" % item)