15 #paths for cover and stego
16 path_stego = '/home/couturie/ajeter/stego/'
17 path_cover = '/home/couturie/ajeter/cover/'
20 M=18532395500947174450709383384936679868383424444311405679463280782405796233163977*39688644836832882526173831577536117815818454437810437210221644553381995813014959
21 X=18532395500947174450709383384936679868383424444311
33 acc = acc + 2**(n-i-1)
38 """Convertit un nombre en binaire"""
40 res = [0 for i in xrange(n)]
53 return 1 if a != b else 0
56 e1b,e2b = bin(e1,h),bin(e2,h)
57 d = dec([xorb(e1b[j],e2b[j]) for j in xrange(h)],h)
60 def lit(d,(indx,indy)):
69 def forward(H_hat,x,message,lnm,rho):
70 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
73 wght = [infinity for _ in xrange(int(2**h))]
75 newwght = [0 for _ in xrange(int(2**h))]
77 # rho= [1 for _ in xrange(len(x))]
80 while i < nbblock: # pour chaque bit du message
81 for j in xrange(w): # pour chaque colonne de H_hat
82 #print indx, "en entrant",wght
84 while k < int(2**h): # pour chaque ligne de H
85 w0 = wght[k] + x[indx]*rho[indx]
86 w1 = wght[xor(k,H_hat[j],h)] + (1-x[indx])*rho[indx]
92 newwght[k] = min(w0,w1)
95 wght = [t for t in newwght]
96 #print " apres calcul",wght
98 for j in xrange(int(2**(h-1))): # pour chaque colonne de H
99 wght[j] = wght[2*j + message[indm]]
100 wght = wght[:int(pow(2,h-1))] + [infinity for _ in xrange(int(pow(2,h)-pow(2,h-1)))]
103 start = np.argmin(wght)
107 def backward(start,H_hat,x,message,lnm,path):
108 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
109 indx,indm = len(x)-1,lnm-1
110 state = 2*start + message[indm]
112 # l'initialisation de state n'est pas optimale...
119 for j in l: # pour chaque colonne de H_hat
120 y[indx] = lit(path,(indx,state))
121 state = xor(state,y[indx]*H_hat[j],h)
123 state = 2*state + message[indm]
126 return [int(t) for t in y]
133 def trouve_H_hat(n,m,h):
137 index = min(int(alpha),9)
142 4 : [81, 95, 107, 121],
143 5 : [75, 95, 97, 105, 117],
144 6 : [73, 83, 95, 103, 109, 123],
145 7 : [69, 77, 93, 107, 111, 115, 121],
146 8 : [69, 79, 81, 89, 93, 99, 107, 119],
147 9 : [69, 79, 81, 89, 93, 99, 107, 119, 125]
152 def stc(x,rho,message):
154 (mat,taille_suff) = trouve_H_hat(len(x),len(message),7)
155 x_b = x[:taille_suff]
156 (start,path) = forward(mat,x_b,message,lnm,rho)
157 return (x_b,backward(start,mat,x_b,message,lnm,path),mat)
177 def prod(H_hat,lnm,y):
178 (h,w) = int(log(max(H_hat),2))+1, len(H_hat)
181 V=[0 for _ in range(len(y))]
183 while i < lnm: # pour chaque ligne
184 V=[0 for _ in range(len(y))]
185 k = max([(i-h+1)*w,0])
187 for j in xrange(min([i+1,h])): #nbre de blocks presents sur la ligne i
188 for l in xrange(w): # pour chaque collone de H_hat
189 V[k] = bin(H_hat[l],h)[h-i-1+j+dec]
192 sol.append(np.dot(np.array(V),np.array(y)))
197 #print "dot",np.dot(H,y),H.shape
199 return sol#list(np.dot(H,y))
206 if x[i] % 2 != y[i]%2 :
216 def conversion(nombre, base, epsilon = 0.00001 ):
217 ''' Soit nombre écrit en base 10, le retourne en base base'''
218 if not 2 <= base <= 36:
219 raise ValueError, "La base doit être entre 2 et 36"
220 if not base == 2 and '.' in str(nombre):
221 raise ValueError, "La partie décimale n'est pas gérée pour les bases\
223 # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
225 abc = string.digits + string.letters
232 if '.' in str(nombre):
233 entier,decimal = int(str(nombre).split('.')[0]),\
234 float('.'+str(nombre).split('.')[1])
236 entier,decimal = int(str(nombre)),0
238 entier, rdigit = divmod( entier, base )
239 result = abc[rdigit] + result
240 flotante, decimalBin = 1./float(base),''
241 while flotante > epsilon :
242 if decimal >= flotante:
247 flotante = flotante/float(base)
248 if '1' in decimalBin :
249 reste = '.'+decimalBin
250 while reste[-1]=='0':
254 return sign + result + reste
258 '''Récupère le bit en position pos de X.
259 Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
260 On fera attention à ce que :
261 - on compte à partir du point,
262 - l'élément juste à gauche du point est en position 1,
263 - celui juste à droite est en position -1.'''
265 entier = conversion(X,2)
267 entier, decimal = entier.split('.')
273 entier = entier.replace('-','')
274 entier = entier.zfill(abs(pos))
275 decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]
277 return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])
281 '''Fixe le bit pos de X à la valeur y.
282 Le fonctionnement est similaire à getBit :
283 - on compte à partir du point,
284 - l'élément juste à gauche du point est en position 1,
285 - celui juste à droite est en position -1.'''
287 entier = conversion(X,2)
289 entier, decimal = entier.split('.')
292 entier = list(entier.zfill(abs(pos)))
293 decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
295 entier[len(entier)-pos]=str(int(y))
297 decimal[-pos-1] = str(int(y))
299 return int(''.join(entier),2)
302 for k in range(len(decimal)):
303 S += 1./2**(k+1)*int(decimal[k])
304 return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])
309 return ''.join('01'[(ai >> x) & 1] for x in xrange(7, -1, -1))
316 for j in list(a2b(i)):
323 return sum(map(lambda z: int(x[z]) and 2**(len(x) - z - 1),
324 range(len(x)-1, -1, -1)))
326 def conv_list_bit(L):
328 for j in range(len(L)/8):
329 L2.append(chr(toDecimal("".join(L[j*8:(j+1)*8]))))
332 def Denary2Binary(n):
333 '''convert denary integer n to binary string bStr'''
335 if n < 0: raise ValueError, "must be a positive integer"
336 if n == 0: return '0'
338 bStr = str(n % 2) + bStr
343 def compute_filter_sobel(level,image):
345 level2= array(level2.getdata()).flatten()
350 level2_im=im.new('L',image.size)
351 level2_im.putdata(level2)
353 cv_im = cv.CreateImageHeader(image.size, cv.IPL_DEPTH_8U, 1)
354 cv.SetData(cv_im, level2_im.tostring())
355 dst16 = cv.CreateImage(cv.GetSize(cv_im), cv.IPL_DEPTH_16S, 1)
357 laplace = cv.Sobel(cv_im, dst16,1, 1,7)
359 dst8 = cv.CreateImage (cv.GetSize(cv_im), cv.IPL_DEPTH_8U, 1)
360 cv.ConvertScale(dst16,dst8)
361 processed=im.fromstring("L", cv.GetSize(dst8), dst8.tostring())
362 # cv.ShowImage ('canny', dst8)
369 def compute_list_bit_to_change(threshold,processed):
374 if (processed[l]>=threshold):
382 def compute_filter_canny(level,image):
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))
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)
404 canny = cv.CreateImage(cv.GetSize(cv_im), 8, 1)
406 List_bit_to_change=set([])
411 cv.Canny(gray, canny, mean-1*std, mean+1*std,3) #avant 10 255
412 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
413 processed= array(processed.getdata()).flatten()
414 List3=set(compute_list_bit_to_change(100,processed))
416 cv.Canny(gray, canny, mean-1*std, mean+1*std,5) #avant 10 255
417 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
418 processed= array(processed.getdata()).flatten()
419 List5=set(compute_list_bit_to_change(100,processed))
421 cv.Canny(gray, canny, mean-1*std, mean+1*std,7) #avant 10 255
422 processed=im.fromstring("L", cv.GetSize(canny), canny.tostring())
423 processed= array(processed.getdata()).flatten()
424 List7=set(compute_list_bit_to_change(100,processed))
426 nb_bit_embedded=(512*512/10)+40
427 AvailablePixel3=List3
428 AvailablePixel5=AvailablePixel3.union(List5)
429 AvailablePixel7=AvailablePixel5.union(List7)
430 if len(AvailablePixel3)>nb_bit_embedded:
432 WorkingPixel=AvailablePixel3
433 elif len(AvailablePixel5)>nb_bit_embedded:
435 WorkingPixel=AvailablePixel5
436 elif len(AvailablePixel7)>nb_bit_embedded:
438 WorkingPixel=AvailablePixel7
441 WorkingPixel=range(len(level2))
443 print "avail P3",len(AvailablePixel3)
444 print "avail P5",len(AvailablePixel5)
445 print "avail P7",len(AvailablePixel7)
447 print "size WorkingPixel",len(WorkingPixel)
448 Weight=[0 for _ in WorkingPixel]
451 for i in WorkingPixel:
452 if step>=1 and i in List3:
454 if step>=2 and i in List5 and Weight[l]==0:
456 if step>=3 and i in List7 and Weight[l]==0:
458 if step>=4 and Weight[l]==0:
465 List_bit_to_change=WorkingPixel
471 return [List_bit_to_change,Weight]
483 def mystego(filein, fileout):
485 dd = dd.convert('RGB')
486 red, green, blue = dd.split()
489 [List_bit_to_change,Weight]=compute_filter_canny(level,dd)
490 level= array(level.getdata()).flatten()
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)