comparison data_generation/transformations/Rature.py @ 167:1f5937e9e530

More moves - transformations into data_generation, added "deep" folder
author Dumitru Erhan <dumitru.erhan@gmail.com>
date Fri, 26 Feb 2010 14:15:38 -0500
parents transformations/Rature.py@7640cb31cf1f
children
comparison
equal deleted inserted replaced
166:17ae5a1a4dd1 167:1f5937e9e530
1 #!/usr/bin/python
2 # coding: utf-8
3
4 '''
5 Ajout d'une rature sur le caractère. La rature est en fait un 1 qui recoit une
6 rotation et qui est ensuite appliqué sur le caractère. Un grossissement, puis deux
7 erosions sont effectuees sur le 1 afin qu'il ne soit plus reconnaissable.
8 Il y a des chances d'avoir plus d'une seule rature !
9
10 Il y a 15% d'effectuer une rature.
11
12 Ce fichier prend pour acquis que les images sont donnees une a la fois
13 sous forme de numpy.array de 1024 (32 x 32) valeurs entre 0 et 1.
14
15 Sylvain Pannetier Lebeuf dans le cadre de IFT6266, hiver 2010
16
17 '''
18
19 import numpy, Image, random
20 import scipy.ndimage.morphology
21 from pylearn.io import filetensor as ft
22
23
24 class Rature():
25
26 def __init__(self,seed=1256):
27 self.angle=0 #Angle en degre de la rotation (entre 0 et 180)
28 self.numero=0 #Le numero du 1 choisi dans la banque de 1
29 self.gauche=-1 #Le numero de la colonne la plus a gauche contenant le 1
30 self.droite=-1
31 self.haut=-1
32 self.bas=-1
33 self.faire=1 #1=on effectue et 0=fait rien
34
35 self.crop_haut=0
36 self.crop_gauche=0 #Ces deux valeurs sont entre 0 et 31 afin de definir
37 #l'endroit ou sera pris le crop dans l'image du 1
38
39 self.largeur_bande=-1 #La largeur de la bande
40 self.smooth=-1 #La largeur de la matrice carree servant a l'erosion
41 self.nb_ratures=-1 #Le nombre de ratures appliques
42 self.fini=0 #1=fini de mettre toutes les couches 0=pas fini
43 self.complexity=0 #Pour garder en memoire la complexite si plusieurs couches sont necessaires
44 self.seed=seed
45
46 #numpy.random.seed(self.seed)
47
48 f3 = open('/data/lisa/data/ift6266h10/un_rature.ft') #Doit etre sur le reseau DIRO.
49 #f3 = open('/home/sylvain/Dropbox/Msc/IFT6266/donnees/un_rature.ft')
50 #Il faut arranger le path sinon
51 w=ft.read(f3)
52 f3.close()
53 self.d=(w.astype('float'))/255
54
55 self.patch=self.d[0].reshape((32,32)) #La patch de rature qui sera appliquee sur l'image
56
57 def get_settings_names(self):
58 return ['angle','numero','faire','crop_haut','crop_gauche','largeur_bande','smooth','nb_ratures']
59
60 def get_seed(self):
61 return self.seed
62
63 def regenerate_parameters(self, complexity,next_rature = False):
64
65
66 self.numero=random.randint(0,4999) #Ces bornes sont inclusives !
67 self.fini=0
68 self.complexity=complexity
69
70 if float(complexity) > 0:
71
72 self.gauche=self.droite=self.haut=self.bas=-1 #Remet tout a -1
73
74 self.angle=int(numpy.random.normal(90,100*complexity))
75
76 self.faire=numpy.random.binomial(1,0.15) ##### 15% d'effectuer une rature #####
77 if next_rature:
78 self.faire = 1
79 #self.faire=1 #Pour tester seulement
80
81 self.crop_haut=random.randint(0,17)
82 self.crop_gauche=random.randint(0,17)
83 if complexity <= 0.25 :
84 self.smooth=6
85 elif complexity <= 0.5:
86 self.smooth=5
87 elif complexity <= 0.75:
88 self.smooth=4
89 else:
90 self.smooth=3
91
92 p = numpy.random.rand()
93 if p < 0.5:
94 self.nb_ratures= 1
95 else:
96 if p < 0.8:
97 self.nb_ratures = 2
98 else:
99 self.nb_ratures = 3
100
101 #Creation de la "patch" de rature qui sera appliquee sur l'image
102 if self.faire == 1:
103 self.get_size()
104 self.get_image_rot() #On fait la "patch"
105
106 else:
107 self.faire=0 #On ne fait rien si complexity=0 !!
108
109 return self._get_current_parameters()
110
111
112 def get_image_rot(self):
113 image2=(self.d[self.numero].reshape((32,32))[self.haut:self.bas,self.gauche:self.droite])
114
115 im = Image.fromarray(numpy.asarray(image2*255,dtype='uint8'))
116
117 #La rotation et le resize sont de belle qualite afin d'avoir une image nette
118 im2 = im.rotate(self.angle,Image.BICUBIC,expand=False)
119 im3=im2.resize((50,50),Image.ANTIALIAS)
120
121 grosse=numpy.asarray(numpy.asarray(im3)/255.0,dtype='float32')
122 crop=grosse[self.haut:self.haut+32,self.gauche:self.gauche+32]
123
124 self.get_patch(crop)
125
126 def get_patch(self,crop):
127 smooting = numpy.ones((self.smooth,self.smooth))
128 #Il y a deux erosions afin d'avoir un beau resultat. Pas trop large et
129 #pas trop mince
130 trans=scipy.ndimage.morphology.grey_erosion\
131 (crop,size=smooting.shape,structure=smooting,mode='wrap')
132 trans1=scipy.ndimage.morphology.grey_erosion\
133 (trans,size=smooting.shape,structure=smooting,mode='wrap')
134
135
136 patch_img=Image.fromarray(numpy.asarray(trans1*255,dtype='uint8'))
137
138 patch_img2=patch_img.crop((4,4,28,28)).resize((32,32)) #Pour contrer les effets de bords !
139
140 trans2=numpy.asarray(numpy.asarray(patch_img2)/255.0,dtype='float32')
141
142
143 #Tout ramener entre 0 et 1
144 trans2=trans2-trans2.min() #On remet tout positif
145 trans2=trans2/trans2.max()
146
147 #La rayure a plus de chance d'etre en bas ou oblique le haut a 10h
148 if random.random() <= 0.5: #On renverse la matrice dans ce cas
149 for i in xrange(0,32):
150 self.patch[i,:]=trans2[31-i,:]
151 else:
152 self.patch=trans2
153
154
155
156
157 def get_size(self):
158 image=self.d[self.numero].reshape((32,32))
159
160 #haut
161 for i in xrange(0,32):
162 for j in xrange(0,32):
163 if(image[i,j]) != 0:
164 if self.haut == -1:
165 self.haut=i
166 break
167 if self.haut > -1:
168 break
169
170 #bas
171 for i in xrange(31,-1,-1):
172 for j in xrange(0,32):
173 if(image[i,j]) != 0:
174 if self.bas == -1:
175 self.bas=i
176 break
177 if self.bas > -1:
178 break
179
180 #gauche
181 for i in xrange(0,32):
182 for j in xrange(0,32):
183 if(image[j,i]) != 0:
184 if self.gauche == -1:
185 self.gauche=i
186 break
187 if self.gauche > -1:
188 break
189
190 #droite
191 for i in xrange(31,-1,-1):
192 for j in xrange(0,32):
193 if(image[j,i]) != 0:
194 if self.droite == -1:
195 self.droite=i
196 break
197 if self.droite > -1:
198 break
199
200
201 def _get_current_parameters(self):
202 return [self.angle,self.numero,self.faire,self.crop_haut,self.crop_gauche,self.largeur_bande,self.smooth,self.nb_ratures]
203
204 def transform_image(self, image):
205 if self.faire == 0: #Rien faire !!
206 return image
207
208 if self.fini == 0: #S'il faut rajouter des couches
209 patch_temp=self.patch
210 for w in xrange(1,self.nb_ratures):
211 self.regenerate_parameters(self.complexity,1)
212 for i in xrange(0,32):
213 for j in xrange(0,32):
214 patch_temp[i,j]=max(patch_temp[i,j],self.patch[i,j])
215 self.fini=1
216 self.patch=patch_temp
217
218 for i in xrange(0,32):
219 for j in xrange(0,32):
220 image[i,j]=max(image[i,j],self.patch[i,j])
221 self.patch*=0 #Remise a zero de la patch (pas necessaire)
222 return image
223
224
225 #---TESTS---
226
227 def _load_image():
228 f = open('/home/sylvain/Dropbox/Msc/IFT6266/donnees/lower_test_data.ft') #Le jeu de donnees est en local.
229 d = ft.read(f)
230 w=numpy.asarray(d[0:1000])
231 return (w/255.0).astype('float')
232
233 def _test(complexite):
234 img=_load_image()
235 transfo = Rature()
236 for i in xrange(0,10):
237 img2=img[random.randint(0,1000)]
238 pylab.imshow(img2.reshape((32,32)))
239 pylab.show()
240 print transfo.get_settings_names()
241 print transfo.regenerate_parameters(complexite)
242 img2=img2.reshape((32,32))
243
244 img2_trans=transfo.transform_image(img2)
245
246 pylab.imshow(img2_trans.reshape((32,32)))
247 pylab.show()
248
249
250 if __name__ == '__main__':
251 from pylearn.io import filetensor as ft
252 import pylab
253 _test(1)
254
255