15 #paths for cover and stego
16 path_stego = '/home/couturie/ajeter/stego/'
17 path_cover = '/home/couturie/ajeter/cover/'
27 acc = acc + 2**(n-i-1)
32 """Convertit un nombre en binaire"""
34 res = [0 for i in xrange(n)]
47 return 1 if a != b else 0
50 e1b,e2b = bin(e1,h),bin(e2,h)
51 d = dec([xorb(e1b[j],e2b[j]) for j in xrange(h)],h)
54 def lit(d,(indx,indy)):
63 def forward(H_hat,x,message,lnm,rho):
64 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
67 wght = [infinity for _ in xrange(int(2**h))]
69 newwght = [0 for _ in xrange(int(2**h))]
71 # rho= [1 for _ in xrange(len(x))]
74 while i < nbblock: # pour chaque bit du message
75 for j in xrange(w): # pour chaque colonne de H_hat
76 #print indx, "en entrant",wght
78 while k < int(2**h): # pour chaque ligne de H
79 w0 = wght[k] + x[indx]*rho[indx]
80 w1 = wght[xor(k,H_hat[j],h)] + (1-x[indx])*rho[indx]
86 newwght[k] = min(w0,w1)
89 wght = [t for t in newwght]
90 #print " apres calcul",wght
92 for j in xrange(int(2**(h-1))): # pour chaque colonne de H
93 wght[j] = wght[2*j + message[indm]]
94 wght = wght[:int(pow(2,h-1))] + [infinity for _ in xrange(int(pow(2,h)-pow(2,h-1)))]
97 start = np.argmin(wght)
101 def backward(start,H_hat,x,message,lnm,path):
102 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
103 indx,indm = len(x)-1,lnm-1
104 state = 2*start + message[indm]
106 # l'initialisation de state n'est pas optimale...
113 for j in l: # pour chaque colonne de H_hat
114 y[indx] = lit(path,(indx,state))
115 state = xor(state,y[indx]*H_hat[j],h)
117 state = 2*state + message[indm]
120 return [int(t) for t in y]
127 def trouve_H_hat(n,m,h):
131 index = min(int(alpha),9)
136 4 : [81, 95, 107, 121],
137 5 : [75, 95, 97, 105, 117],
138 6 : [73, 83, 95, 103, 109, 123],
139 7 : [69, 77, 93, 107, 111, 115, 121],
140 8 : [69, 79, 81, 89, 93, 99, 107, 119],
141 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
146 def stc(x,rho,message):
148 (mat,taille_suff) = trouve_H_hat(len(x),len(message),7)
149 x_b = x[:taille_suff]
150 (start,path) = forward(mat,x_b,message,lnm,rho)
151 return (x_b,backward(start,mat,x_b,message,lnm,path),mat)
171 def prod(H_hat,lnm,y):
172 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
175 V=[0 for _ in range(len(y))]
177 while i < lnm: # pour chaque ligne
178 V=[0 for _ in range(len(y))]
179 k = max([(i-h+1)*w,0])
181 for j in xrange(min([i+1,h])): #nbre de blocks presents sur la ligne i
182 for l in xrange(w): # pour chaque collone de H_hat
183 V[k] = bin(H_hat[l],h)[h-i-1+j+dec]
186 sol.append(np.dot(np.array(V),np.array(y)))
191 #print "dot",np.dot(H,y),H.shape
193 return sol#list(np.dot(H,y))
200 if x[i] % 2 != y[i]%2 :
210 def conversion(nombre, base, epsilon = 0.00001 ):
211 ''' Soit nombre écrit en base 10, le retourne en base base'''
212 if not 2 <= base <= 36:
213 raise ValueError, "La base doit être entre 2 et 36"
214 if not base == 2 and '.' in str(nombre):
215 raise ValueError, "La partie décimale n'est pas gérée pour les bases\
217 # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
219 abc = string.digits + string.letters
226 if '.' in str(nombre):
227 entier,decimal = int(str(nombre).split('.')[0]),\
228 float('.'+str(nombre).split('.')[1])
230 entier,decimal = int(str(nombre)),0
232 entier, rdigit = divmod( entier, base )
233 result = abc[rdigit] + result
234 flotante, decimalBin = 1./float(base),''
235 while flotante > epsilon :
236 if decimal >= flotante:
241 flotante = flotante/float(base)
242 if '1' in decimalBin :
243 reste = '.'+decimalBin
244 while reste[-1]=='0':
248 return sign + result + reste
252 '''Récupère le bit en position pos de X.
253 Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
254 On fera attention à ce que :
255 - on compte à partir du point,
256 - l'élément juste à gauche du point est en position 1,
257 - celui juste à droite est en position -1.'''
259 entier = conversion(X,2)
261 entier, decimal = entier.split('.')
267 entier = entier.replace('-','')
268 entier = entier.zfill(abs(pos))
269 decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]
271 return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])
275 '''Fixe le bit pos de X à la valeur y.
276 Le fonctionnement est similaire à getBit :
277 - on compte à partir du point,
278 - l'élément juste à gauche du point est en position 1,
279 - celui juste à droite est en position -1.'''
281 entier = conversion(X,2)
283 entier, decimal = entier.split('.')
286 entier = list(entier.zfill(abs(pos)))
287 decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
289 entier[len(entier)-pos]=str(int(y))
291 decimal[-pos-1] = str(int(y))
293 return int(''.join(entier),2)
296 for k in range(len(decimal)):
297 S += 1./2**(k+1)*int(decimal[k])
298 return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])
303 return ''.join('01'[(ai >> x) & 1] for x in xrange(7, -1, -1))
310 for j in list(a2b(i)):
317 return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
318 range(len(x)-1, -1, -1)))
320 def conv_list_bit(L):
322 for j in range(len(L)/8):
323 L2.append(chr(toDecimal("".join(L[j*8:(j+1)*8]))))
326 def Denary2Binary(n):
327 '''convert denary integer n to binary string bStr'''
329 if n < 0: raise ValueError, "must be a positive integer"
330 if n == 0: return '0'
332 bStr = str(n % 2) + bStr
337 def compute_filter_sobel(level,image):
339 level2= array(level2.getdata()).flatten()
344 level2_im=im.new('L',image.size)
345 level2_im.putdata(level2)
347 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 1)
348 cv.SetData(cv_im, level2_im.tostring())
349 dst16 = cv.CreateImage(cv.GetSize(cv_im), cv.IPL_DEPTH_16S, 1)
351 laplace = cv.Sobel(cv_im, dst16,1, 1,7)
353 dst8 = cv.CreateImage (cv.GetSize(cv_im), cv.IPL_DEPTH_8U, 1)
354 cv.ConvertScale(dst16,dst8)
355 processed=im.fromstring("L", cv.GetSize(dst8), dst8.tostring())
356 # cv.ShowImage ('canny', dst8)
363 def compute_list_bit_to_change(threshold,processed):
368 if (processed[l]>=threshold):
376 def compute_filter_canny(level,image):
378 level2= array(level2.getdata()).flatten()
383 level2_im=im.new('L',image.size)
384 level2_im.putdata(level2)
385 level2_im=im.merge("RGB",(level2_im,level2_im,level2_im))
387 mean=numpy.mean(level2)
388 std=numpy.std(level2)
390 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 3)
391 cv.SetData(cv_im, level2_im.tostring())
393 yuv = cv.CreateImage(cv.GetSize(cv_im), 8, 3)
394 gray = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
395 cv.CvtColor(cv_im, yuv, cv.CV_BGR2YCrCb)
396 cv.Split(yuv, gray, None, None, None)
398 canny = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
400 List_bit_to_change=set([])
405 cv.Canny(gray, canny, mean-1*std, mean+1*std,3) #avant 10 255
406 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
407 processed= array(processed.getdata()).flatten()
408 List3=set(compute_list_bit_to_change(100,processed))
410 cv.Canny(gray, canny, mean-1*std, mean+1*std,5) #avant 10 255
411 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
412 processed= array(processed.getdata()).flatten()
413 List5=set(compute_list_bit_to_change(100,processed))
415 cv.Canny(gray, canny, mean-1*std, mean+1*std,7) #avant 10 255
416 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
417 processed= array(processed.getdata()).flatten()
418 List7=set(compute_list_bit_to_change(100,processed))
420 nb_bit_embedded=(512*512/10)+40
421 AvailablePixel3=List3
422 AvailablePixel5=AvailablePixel3.union(List5)
423 AvailablePixel7=AvailablePixel5.union(List7)
424 if len(AvailablePixel3)>nb_bit_embedded:
426 WorkingPixel=AvailablePixel3
427 elif len(AvailablePixel5)>nb_bit_embedded:
429 WorkingPixel=AvailablePixel5
430 elif len(AvailablePixel7)>nb_bit_embedded:
432 WorkingPixel=AvailablePixel7
435 WorkingPixel=range(len(level2))
437 print "avail P3",len(AvailablePixel3)
438 print "avail P5",len(AvailablePixel5)
439 print "avail P7",len(AvailablePixel7)
441 print "size WorkingPixel",len(WorkingPixel)
442 Weight=[0 for _ in WorkingPixel]
445 for i in WorkingPixel:
446 if step>=1 and i in List3:
448 if step>=2 and i in List5 and Weight[l]==0:
450 if step>=3 and i in List7 and Weight[l]==0:
452 if step>=4 and Weight[l]==0:
459 List_bit_to_change=WorkingPixel
465 return [List_bit_to_change,Weight]
477 def mystego(filein, fileout):
479 dd = dd.convert('RGB')
480 red, green, blue = dd.split()
483 [List_bit_to_change,Weight]=compute_filter_canny(level,dd)
484 level= array(level.getdata()).flatten()
495 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
496 X=18532395500947174450709383384936679868383424444311
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. 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:-)"
508 message=message[0:len(message)/1]
509 leng_msg=len(message)
510 message=message+((leng_msg+7)/8*8-leng_msg)*" "
511 leng_msg=len(message)
513 leng='%08d'%len(message)
519 leng_error=int(len_leng)
521 List_pack=a2b_list(leng_cor)
524 while len(List_random)<len(List_bit_to_change):
526 List_random.extend(Denary2Binary(X))
529 for i in range(leng_msg/8):
530 m=message[i*8:(i+1)*8]
532 m_bin=a2b_list(m_cor)
534 List_pack.extend(m_bin)
543 Support=[getBit(level[l],bit_to_read) for l in List_bit_to_change]
546 Message=[(int(List_pack[l])^int(List_random[l])) for l in xrange(len(List_pack))]
548 print "support",len(List_bit_to_change)
549 print "message",len(Message)
550 print "weight",len(Weight)
552 (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_bit_to_change:
566 if(size_mesg<len(Stc_message)):
567 b=getBit(level[l],bit_to_read)
568 if b!=Stc_message[size_mesg]:
570 level[l]=float64(setBit(level[l],bit_to_read,Stc_message[size_mesg]))
573 print 'size mesg',size_mesg
574 print 'val mod',val_mod
575 print 'len message',len(Message),len(List_pack)
579 zz3=im.new('L',dd.size)
587 listing = os.listdir(path_cover)
596 for infile in listing:
597 print "current file is: " + infile, path_stego+infile
598 mystego(path_cover+infile,path_stego+infile)