view transformations/Occlusion.py @ 61:cc4be6b25b8e

Data iterator alternating between NIST/font/captcha, removed the use of batches, keep track of labels (Not fully done yet)
author boulanni <nicolas_boulanger@hotmail.com>
date Mon, 08 Feb 2010 23:45:17 -0500
parents 27bf31dca87d
children f3e4328e3514
line wrap: on
line source

#!/usr/bin/python
# coding: utf-8

'''
Ajout de bruit d'occlusion dans l'image originale.

Le bruit provient d'un echantillon pris dans la seconde image puis rajoutee a
gauche ou a droite de l'image originale. De plus, il se peut aussi que le
bruit soit rajoute sur l'image originale, mais en plus pâle.

Il faut s'assurer d'avoir le fichier echantillon_occlusion.ft (voir "files" sur assembla) 
dans le repertoire ou est effectuee l'execution de Occlusion.py. Sinon, 
simplement changer le "path" sur la ligne 46

Sylvain Pannetier Lebeuf dans le cadre de IFT6266, hiver 2010

'''


import numpy
import scipy
import pylab
from pylearn.io import filetensor as ft

class Occlusion():
    
    def __init__(self):
        #Ces 4 variables representent la taille du "crop" sur l'image2
        #Ce "crop" est pris a partie de image1[15,15], le milieu de l'image1
        self.haut=2
        self.bas=2
        self.gauche=2
        self.droite=2
        
        #Ces deux variables representent le deplacement en x et y par rapport
        #au milieu du bord gauche ou droit
        self.x_arrivee=0
        self.y_arrivee=0
        
        #Cette variable =1 si l'image est mise a gauche et -1 si a droite
        #et =0 si au centre, mais plus pale
        self.endroit=-1
        
        #Cette variable determine l'opacite de l'ajout dans le cas ou on est au milieu
        self.opacite=0.5    #C'est completement arbitraire. Possible de le changer si voulu
        
        f3 = open('/data/lisa/data/ift6266h10/echantillon_occlusion.ft')   #Doit etre sur le reseau DIRO.
        #Il faut arranger le path sinon
        w=ft.read(f3)
        f3.close()
        
        self.longueur=len(w)
        self.d=(w.astype('float'))/255
        
        
    def get_settings_names(self):
        return ['haut','bas','gauche','droite','x_arrivee','y_arrivee','endroit','rajout']

    def regenerate_parameters(self, complexity):
        self.haut=min(15,int(numpy.abs(numpy.random.normal(int(7*complexity),2))))
        self.bas=min(15,int(numpy.abs(numpy.random.normal(int(7*complexity),2))))
        self.gauche=min(15,int(numpy.abs(numpy.random.normal(int(7*complexity),2))))
        self.droite=min(15,int(numpy.abs(numpy.random.normal(int(7*complexity),2))))
        if self.haut+self.bas+self.gauche+self.droite==0:   #Tres improbable
            self.haut=1
            self.bas=1
            self.gauche=1
            self.droite=1
        
        #Ces deux valeurs seront controlees afin d'etre certain de ne pas depasser
        self.x_arrivee=int(numpy.abs(numpy.random.normal(0,2))) #Complexity n'entre pas en jeu, pas besoin
        self.y_arrivee=int(numpy.random.normal(0,3)) 
        
        self.rajout=numpy.random.randint(0,self.longueur)  #les bouts de quelle lettre
        
        self.endroit=numpy.random.randint(-1,2) 
        #####Revoir si ces trois dernieres variables sont determinees ici !
        return self._get_current_parameters()

    def _get_current_parameters(self):
        return [self.haut,self.bas,self.gauche,self.droite,self.x_arrivee,self.y_arrivee,self.endroit,self.rajout]
    
    
    def transform_image(self, image):
        #Attrapper le bruit d'occlusion
        bruit=self.d[self.rajout].reshape((32,32))[15-self.haut:15+self.bas+1,15-self.gauche:15+self.droite+1]
        
        if self.x_arrivee+self.gauche+self.droite>32:
            self.endroit*=-1    #On change de bord et on colle sur le cote
            self.x_arrivee=0
        if self.y_arrivee-self.haut <-16:
            self.y_arrivee=self.haut-16#On colle le morceau en haut
        if self.y_arrivee+self.bas > 15:
            self.y_arrivee=15-self.bas  #On colle le morceau en bas
            
        if self.endroit==-1:    #a gauche
            image[(16+self.y_arrivee-self.haut):(16+self.y_arrivee+self.bas+1),(self.x_arrivee):(self.x_arrivee+self.gauche+self.droite+1)]=image[(16+self.y_arrivee-self.haut):(16+self.y_arrivee+self.bas+1),(self.x_arrivee):(self.x_arrivee+self.gauche+self.droite+1)]+bruit
        
        elif self.endroit==1: #a droite
            image[(16+self.y_arrivee-self.haut):(16+self.y_arrivee+self.bas+1),(31-self.x_arrivee-self.gauche-self.droite):(31-self.x_arrivee+1)]=image[(16+self.y_arrivee-self.haut):(16+self.y_arrivee+self.bas+1),(31-self.x_arrivee-self.gauche-self.droite):(31-self.x_arrivee+1)]+bruit
        
        elif self.endroit==0:    #au milieu
            image[(16-self.haut):(16+self.bas+1),(16-self.gauche):(16+self.droite+1)]=image[(16-self.haut):(16+self.bas+1),(16-self.gauche):(16+self.droite+1)]+(bruit*self.opacite)
        
        #renormaliser le tout. Toutes les entrees doivent etre entre 0 et 1
        for ii in xrange(0,32):
            for jj in xrange(0,32):
                image[ii,jj]=min(1,image[ii,jj])
        
        return image
        
#---TESTS---

def _load_image():
    f = open('/home/sylvain/Dropbox/Msc/IFT6266/donnees/lower_test_data.ft')  #Le jeu de donnees est en local. 
    d = ft.read(f)
    w=numpy.asarray(d[numpy.random.randint(0,50)])
    return (w/255.0).astype('float')

def _test(complexite):
    
    transfo = Occlusion()
    for i in xrange(0,20):
        img = _load_image()
        pylab.imshow(img.reshape((32,32)))
        pylab.show()
        print transfo.get_settings_names()
        print transfo.regenerate_parameters(complexite)
        
        img_trans=transfo.transform_image(img.reshape((32,32)))
        
        pylab.imshow(img_trans.reshape((32,32)))
        pylab.show()
    

if __name__ == '__main__':
    import pylab
    _test(0.5)