view transformations/Rature.py @ 58:fd02fd7e6557

Contraste de rature plus prononce, il y a maintenant rature avec proba=complexity, la clarte et la largeur de la bande ont maintenant une composante aleatoire
author SylvainPL <sylvain.pannetier.lebeuf@umontreal.ca>
date Mon, 08 Feb 2010 13:57:46 -0500
parents 5848e88f7a7a
children 7949f46b03e0
line wrap: on
line source

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

'''
Ajout de rature sur le caractère. La rature peut etre horizontale, verticale 
(dans ces deux cas, l'amplacement de la bande est aleatoire) ou sur la diagonale
(et anti-diagonale).

La largeur de la bande ainsi que sa clarté sont definies a l'aide de complexity
et d'une composante aleatoire.
clarte: 0=blanc et 1=noir

Ce fichier prend pour acquis que les images sont donnees une a la fois
sous forme de numpy.array de 1024 (32 x 32) valeurs entre 0 et 1.

Sylvain Pannetier Lebeuf dans le cadre de IFT6266, hiver 2010

'''

import numpy
import random

class Rature():
   
    def __init__(self):
        self.largeur=2  #Largeur de la bande
        self.deplacement=0  #Deplacement par rapport au milieu
        self.orientation=0  #0=horizontal, 1=vertical, 2=oblique
        self.clarte=0.5 #Clarte de la ligne appliquee
        self.faire=1  #Si ==1, on applique une rature

    def get_settings_names(self):
        return ['orientation','deplacement','clarte','faire']

    def regenerate_parameters(self, complexity):
        #Il faut choisir parmis vertical, horizontal et diagonal.
        #La methode n'est pas exacte, mais un peu plus rapide que generer un int.
        #Complexity n'a rien a voir avec ce choix
        
        choix=numpy.random.random()
        
        if choix <0.34:
            self.orientation=0
        elif choix <0.67:
            self.orientation=1
        else:
            self.orientation=2
            
        self.largeur=min(32,max(1,int(numpy.ceil(complexity*5)*numpy.random.normal(1,float(complexity)/2))))
        self.clarte=min(1,max(0,complexity*numpy.random.normal(1,float(complexity)/2)))
        self.faire=numpy.random.binomial(1,float(complexity))
        
        return self._get_current_parameters()

    def _get_current_parameters(self):
        return [self.orientation,self.largeur,self.clarte,self.faire]

    def transform_image(self, image):
        if self.faire == 0:
            return image
        
        if self.orientation == 0:
            return self._horizontal(image)
        elif self.orientation == 1:
            return self._vertical(image)
        else:
            return self._oblique(image)
        
    def _horizontal(self,image):
        self.deplacement=numpy.random.normal(0,5)
        #On s'assure de rester dans l'image
        if self.deplacement < -16:  #Si on recule trop
            self.deplacement = -16
        if self.deplacement+self.largeur > 16: #Si on avance trop
            self.deplacement=16-self.largeur
        for i in xrange(0,self.largeur):
            for j in xrange(0,32):
                image[i+15+self.deplacement,j]=min(1,max(image[i+15+self.deplacement,j],self.clarte))
        return image
    
    def _vertical(self,image):
        self.deplacement=numpy.random.normal(0,5)
        #On s'assure de rester dans l'image
        if self.deplacement < -16:  #Si on recule trop
            self.deplacement = -16
        if self.deplacement+self.largeur > 16: #Si on avance trop
            self.deplacement=16-self.largeur
        for i in xrange(0,self.largeur):
            for j in xrange(0,32):
                image[j,i+15+self.deplacement]=min(1,max(image[j,i+15+self.deplacement],self.clarte))
        return image
    
    def _oblique(self,image):
        decision=numpy.random.random()
        D=numpy.zeros((32,32)) #La matrice qui sera additionnee
        for i in xrange(int(-numpy.floor(self.largeur/2)),int(numpy.ceil((self.largeur+1)/2))):
            D+=numpy.eye(32,32,i)
        if decision<0.5: #On met tout sur l'anti-diagonale
            D = D[:,::-1]
        D*=self.clarte
        for i in xrange(0,32):
            for j in xrange(0,32):
                image[i,j]=min(1,max(image[i,j],D[i,j])) 
        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[1])
    return (w/255.0).astype('float')

def _test(complexite):
    img=_load_image()
    transfo = Rature()
    pylab.imshow(img.reshape((32,32)))
    pylab.show()
    print transfo.get_settings_names()
    print transfo.regenerate_parameters(complexite)
    img=img.reshape((32,32))
    
    img_trans=transfo.transform_image(img)
    
    pylab.imshow(img_trans.reshape((32,32)))
    pylab.show()
    

if __name__ == '__main__':
    from pylearn.io import filetensor as ft
    import pylab
    _test(0.8)