14 path_stego = '/home/couturie/ajeter/stego/'
15 path_cover = '/home/couturie/ajeter/cover/'
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=len(List3)/2
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))
440 print "avail P3",len(AvailablePixel3)
441 print "avail P5",len(AvailablePixel5)
442 print "avail P7",len(AvailablePixel7)
444 print "size WorkingPixel",len(WorkingPixel)
445 Weight=[0 for _ in WorkingPixel]
448 for i in WorkingPixel:
449 if step>=1 and i in List3:
451 if step>=2 and i in List5 and Weight[l]==0:
453 if step>=3 and i in List7 and Weight[l]==0:
455 if step>=4 and Weight[l]==0:
462 List_bit_to_change=WorkingPixel
466 Size_message=nb_bit_embedded
468 return [Size_message,Weight,List3]
480 def mystego(filein, fileout):
482 dd = dd.convert('RGB')
483 red, green, blue = dd.split()
486 [Size_message,Weight,List_support]=compute_filter_canny(level,dd)
487 level= array(level.getdata()).flatten()
494 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
495 X=18532395500947174450709383384936679868383424444311
508 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:-)"
511 message=message+message+message+message+message+message+message+message
512 message=message[0:len(message)/1]
513 leng_msg=len(message)
514 message=message+((leng_msg+7)/8*8-leng_msg)*" "
515 leng_msg=len(message)
517 leng='%08d'%len(message)
523 leng_error=int(len_leng)
525 List_pack=a2b_list(leng_cor)
528 while len(List_random)<Size_message:
530 List_random.extend(Denary2Binary(X))
533 for i in range(leng_msg/8):
534 m=message[i*8:(i+1)*8]
536 m_bin=a2b_list(m_cor)
538 List_pack.extend(m_bin)
541 Support=[getBit(level[l],bit_to_read) for l in List_support]
544 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(Size_message)]
546 print "support",len(List_support)
547 print "message",len(Message)
548 print "weight",len(Weight)
551 (x_b,Stc_message,H_hat) = stc(Support,Weight,Message)
554 print "pourcentage modif",nbdif(x_b,Stc_message)
555 print "taille Stc_message",len(Stc_message)
565 for l in List_support:
566 if(size_mesg<len(Stc_message)):
567 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
570 print 'size mesg',size_mesg
571 print 'len message',len(Message),len(List_pack)
575 zz3=im.new('L',dd.size)
579 list_nb_bit.append(filein)
580 list_nb_bit.append(Size_message)
587 listing = os.listdir(path_cover)
595 for infile in listing:
596 print "current file is: " + infile, path_stego+infile
597 mystego(path_cover+infile,path_stego+infile)