Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 10 sur 10
  1. #1
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut [Image/Java] Moments : centralisés, Hu, Legendre et Zernike

    Bonjour,

    je mets en lignes plusieurs classes permettant de calculer les moments :
    1. Centralisés
    2. Hu
    3. Legendre
    4. Zernike (à venir, découverte d'un petit bug que je dois corriger).



    La classe Image utilisée et simplement une extension de BufferedImage de "java.awt". Il s'agit juste de faciliter l'accès aux valeurs des pixels (surtout en niveaux de gris) à l'aide de méthodes "Pixel(y, x)" qui renvoient la valeur.

    De même la classe "Point" utilise ici deux méthodes qui "getX getY" qui renvoient les coordonnées en X et Y du point.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  2. #2
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut Moments centralisés

    Code java :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
     
    import java.awt.image.BufferedImage;
    import java.awt.image.WritableRaster;
     
    import mathematics.primitives.pointsTiTi.Point;
     
    import measures.BaryBoiteContPeriSurf;
     
    /**
     * <p>Description: Cette classe calcule les moments centres d'une forme. C'est tout simplement les moments cartesiens invariants
     *  par translation.</p>
     * <p>Sources : <html>http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/SHUTLER3/node5.html</html>.</p>
     * <p>Package(s) required: mathematics, measures.</p>
     * <p>Copyright: Copyright (c) 2007-2011.</p>
     * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
     * <p>Updates:<br>
     * 20 Avril 2009 => Creation.</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class Centralized
    {
     
    /** Le tableau contenant les coefficients.*/
    protected double[][] Mu = null ;
    /** Le tableau contenant les coefficients apres normalisation pour obtenir l'invariance d'echelle.*/
    protected double[][] Nu = null ;
    /** L'ordre utilise pour les calculs.*/
    protected int Order = -1 ;
     
     
     
    public Centralized()
    	{
    	}
     
     
    /** Methode qui lance le calcul des moments. Cette methode appelle la methode du meme nom, mais effectue avant le calcul
     *  du barycentre.
     * @param image L'image contenant la forme.
     * @param Order L'ordre maximum a calculer.*/
    public void Compute(BufferedImage image, int Order)
    	{
    	BaryBoiteContPeriSurf bbcps = new BaryBoiteContPeriSurf() ;
    	bbcps.Compute(image, true, null) ;
    	Compute(image, bbcps.Centroid, Order) ;
    	bbcps = null ;
    	}
     
     
     
    /** Methode qui lance le calcul des moments.
     * @param image L'image contenant la forme.
     * @param Barycentre Le barycentre de la forme.
     * @param Order L'ordre maximum a calculer.*/
    public void Compute(BufferedImage image, Point Barycentre, int Order)
    	{
    	if ( image.getType() != BufferedImage.TYPE_BYTE_BINARY )
    		throw new IllegalArgumentException("Only binary image supported (shape index).") ;
    	if ( Order < 0 ) throw new Error("Order < 0") ;
     
    	int p, q, x, y ;
    	double Bx = Barycentre.getX(), By = Barycentre.getY() ;
    	this.Order = Order ;
     
    	Mu = null ;
    	Nu = null ;
    	Mu = new double[Order+1][Order+1] ;
    	Nu = new double[Order+1][Order+1] ;
    	WritableRaster wr = image.getRaster() ;
     
    	for (p=0 ; p <= Order ; p++)
    		for (q=0 ; q <= Order ; q++)
    			Mu[p][q] = Nu[p][q] = 0.0 ;
     
    	for (y=0 ; y < image.getHeight() ; y++)
    		for (x=0 ; x < image.getWidth() ; x++)
    			if ( wr.getSample(x, y, 0) > 0 )
    				for (p=0 ; p <= Order ; p++)
    					for (q=0 ; q <= Order ; q++)
    						Mu[p][q] += Math.pow((double)x-Bx, p) * Math.pow((double)y-By, q) ;
     
    	for (p=0 ; p <= Order ; p++)
    		for (q=0 ; q <= Order ; q++)
    			if ( p+q >= 2 ) Nu[p][q] = Mu[p][q] / Math.pow(Mu[0][0], (int)((p+q)/2)+1) ;
    			else Nu[p][q] = Mu[p][q] / Mu[0][0] ;
     
    	wr = null ;
    	}
     
     
     
     
     
     
     
     
    public double[][] getMu()
    	{
    	return Mu ;
    	}
     
    public double[][] getNu()
    	{
    	return Nu ;
    	}
     
    public int getOrder()
    	{
    	return Order ;
    	}
     
    }
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  3. #3
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut Moments de Hu

    Les méthodes Display, toString, etc. servent juste à écrire/afficher les résultats. Elles peuvent bien évidement être effacées.

    Code java :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
     
    import java.awt.image.BufferedImage;
    import java.awt.image.WritableRaster;
    import java.io.IOException;
     
    import mathematics.primitives.pointsTiTi.Point;
     
    import measures.BaryBoiteContPeriSurf;
     
    /**
     * <p>Description : Cette classe calcule les moments de Hu d'une forme.</p>
     * <p>Sources : <html>http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/SHUTLER3/node8.html</html>.</p>
     * <p>Package(s) required: mathematics, measures..</p>
     * <p>Copyright: Copyright (c) 2007-2011.</p>
     * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
     * <p>Updates:<br>
     * 21 Avril 2009 => Creation.</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class Hu
    {
     
    /** L'ordre des moments de Hu qui est toujours egale a trois.*/
    protected int Order = 3 ;
    /** Le tableau contenant les coefficients des moments centres.*/
    protected double[][] Mu = new double[Order+1][Order+1] ; ;
    /** Le tableau contenant les coefficients apres normalisation pour obtenir l'invariance d'echelle.*/
    protected double[][] Nu = new double[Order+1][Order+1] ; ;
    /** Le tableau contenant les moment de Hu : I1.*/
    protected double[] I = new double[8] ;
     
     
     
     
    public Hu()
    	{
    	}
     
     
     
    /** Methode qui lance le calcul des moments. Cette methode appelle la methode du meme nom, mais effectue avant le calcul du
     *  barycentre.
     * @param image L'image contenant la forme.*/
    public void Compute(BufferedImage image)
    	{
    	BaryBoiteContPeriSurf bbcps = new BaryBoiteContPeriSurf() ;
    	bbcps.Compute(image, true, null) ;
    	Compute(image, bbcps.Centroid) ;
    	bbcps = null ;
    	}
     
     
     
    /** Methode qui lance le calcul des moments.
     * @param image L'image contenant la forme.
     * @param Barycentre Le barycentre de la forme.*/
    public void Compute(BufferedImage image, Point Barycentre)
    	{
    	if ( image.getType() != BufferedImage.TYPE_BYTE_BINARY )
    		throw new IllegalArgumentException("Only binary image supported (shape index).") ;
     
    	int p, q, x, y ;
    	double Bx = Barycentre.getX(), By = Barycentre.getY() ;
    	WritableRaster wr = image.getRaster() ;
     
    	for (p=0 ; p <= Order ; p++)
    		for (q=0 ; q <= Order ; q++)
    			Mu[p][q] = Nu[p][q] = 0.0 ;
     
    	for (y=0 ; y < image.getHeight() ; y++)
    		for (x=0 ; x < image.getWidth() ; x++)
    			if ( wr.getSample(x, y, 0) > 0 )
    				for (p=0 ; p <= Order ; p++)
    					for (q=0 ; q <= Order ; q++)
    						Mu[p][q] += Math.pow((double)x-Bx, p) * Math.pow((double)y-By, q) ;
     
    	for (p=0 ; p <= Order ; p++)
    		for (q=0 ; q <= Order ; q++)
    			if ( p+q >= 2 ) Nu[p][q] = Mu[p][q] / Math.pow(Mu[0][0], (int)((p+q)/2)+1) ;
    			//else Nu[p][q] = Mu[p][q] / Mu[0][0] ;
     
    	I[0] = 0.0 ; // Ne sert à rien.
    	I[1] = Nu[0][2] + Nu[2][0] ;
    	I[2] = Math.pow(Nu[0][2]-Nu[2][0], 2.0) + 4.0*Nu[1][1]*Nu[1][1] ;
    	I[3] = Math.pow(Nu[3][0]-3.0*Nu[1][2], 2.0) + Math.pow(3.0*Nu[2][1]-Nu[0][3], 2.0) ;
    	I[4] = Math.pow(Nu[3][0]+Nu[1][2], 2.0) + Math.pow(Nu[2][1]+Nu[0][3], 2.0) ;
    	I[5] = (Nu[3][0]-3.0*Nu[1][2]) * (Nu[3][0]+Nu[1][2]) * (Math.pow(Nu[3][0]+Nu[1][2], 2.0)
    			- 3.0*Math.pow(Nu[2][1]+Nu[0][3], 2.0)) + (3.0*Nu[2][1]-Nu[0][3])*(Nu[2][1]+Nu[0][3])
    			* (3.0*Math.pow(Nu[3][0]+Nu[1][2], 2.0) - Math.pow(Nu[2][1]+Nu[0][3], 2.0)) ;
    	I[6] = (Nu[2][0]-Nu[0][2]) * (Math.pow(Nu[3][0]+Nu[1][2], 2.0) - Math.pow(Nu[2][1]+Nu[0][3], 2.0)
    			+ 4.0*Nu[1][1]*(Nu[3][0]+Nu[1][2])*(Nu[2][1]+Nu[0][3])) ;
    	I[7] = (3.0*Nu[2][1]-Nu[0][3]) * (Nu[3][0]+Nu[1][2]) * (Math.pow(Nu[3][0]+Nu[1][2], 2.0)
    			- 3.0*Math.pow(Nu[2][1]+Nu[0][3], 2.0)) + (Nu[3][0]-3.0*Nu[1][2]) * (Nu[2][1]+Nu[0][3])
    			* (3.0*Math.pow(Nu[3][0]+Nu[1][2], 2.0) - Math.pow(Nu[2][1]+Nu[0][3], 2.0)) ;
    	}
     
     
     
     
     
     
    /* ------------------------------------------------------- Les getters ------------------------------------------------------- */
    /** Methode qui retourne les valeurs des moments de Hu : I1... I7.
     * @param x Le numero du moment (1...7).
     * @return Le moment de Hu correspondant.*/
    public double getIx(int x)
    	{
    	return I[x] ;
    	}
     
    /** Methode qui retourne le tableau contenant les moments de Hu. Ils sont stockes de 1 a 7, donc pas de decalage de 1 vers le bas.
     * @return Le tableau contenant les moments.*/
    public double[] getI()
    	{
    	return I ;
    	}
     
    public int getOrder()
    	{
    	return Order ;
    	}
     
     
     
     
     
     
     
     
     
     
    /** Methode qui affiche les derniers resultats.*/
    public void DisplayLast()
    	{
    	System.out.println(toString()) ;
    	}
     
     
    /** Methode qui affiche les derniers resultats.
     * @param Separator Le separateur a utiliser.*/
    public void DisplayLast(String Separator)
    	{
    	System.out.println(toString(Separator)) ;
    	}
     
     
    /** Methode qui ecrit les derniers resultats dans un objet de type Appendable.
     * @param out L'objet qui doit implementer l'interface Appendable.*/
    public void appendTo(Appendable out)
    	{
    	appendTo(out, " ") ;
    	}
     
     
    /** Methode qui ecrit les derniers resultats dans un objet de type Appendable.
     * @param out L'objet qui doit implementer l'interface Appendable.
     * @param Separator Le separateur a utiliser.*/
    public void appendTo(Appendable out, String Separator)
    	{
    	try	{
    		for (int i=1 ; i <= 7 ; i++)
    			out.append(String.valueOf(I[i])).append(Separator) ;
    		}
    	catch ( IOException e )
    		{
    		e.printStackTrace() ;
    		throw new Error("Exception levée.") ;
    		}
    	}
     
     
    /** On surcharge la methode pour qu'elle renvoit les derniers resultats.
     * @return Les resultats sous forme de chaines.*/
    public String toString()
    	{
    	return toString(" ") ;
    	}
     
     
    /** On surcharge la methode pour qu'elle renvoit les derniers resultats.
     * @param Separator Le separateur a utiliser.
     * @return Les resultats sous forme de chaines.*/
    public String toString(String Separator)
    	{
    	StringBuilder sb = new StringBuilder() ;
    	this.appendTo(sb) ;
    	return sb.toString() ;
    	}
     
    }
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  4. #4
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut Moments de Legendre

    Voilà deux classes permettant de calculer les moments de Legendre. La première calcule le polynôme de Legendre et la deuxième utilise la première pour en calculer les moments.

    Remarque : le "extends" peut être supprimé car c'est une extension d'une classes Polynomial 'générique' que j'utilise de temps en temps pour modéliser des polynômes.


    Code java :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    import mathematics.functions.Polynomial;
     
    /**
     * <p>Description : Cette classe represente le polynome de Legendre. Une simple extension de la classe Polynom a laquelle on ajoute le calcul des coefficients.</p>
     * <p>Package necessaires : mathematics.</p>
     * <p>Dernieres modifications :<br>
     * 21 Avril 2009 => Creation.</p>
     * <p>Copyright : Copyright (c) 2007.</p>
     * <p>Laboratoire : LSIS.</p>
     * <p>Equipe : Image et Modele, I&M (ex LXAO).</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class LegendrePolynomial extends Polynomial
    {
     
    /** Un petit constructeur qui appelle le constructeur pere et lance le calcul des coefficients en fonction du degres du polynome.
     * @param Degres Le degres du polynome.*/
    public LegendrePolynomial(int Degres)
    	{
    	super(Degres) ;
    	ComputeCoefficients() ;
    	}
     
     
    /** Methode qui calcule les coefficient du polynome de Legendre.*/
    protected void ComputeCoefficients()
    	{
    	int n = Degres ;
     
    	for (int j=0 ; j <= n ; j++)
    		if ( Math.abs(n-j) % 2 != 0 ) Coefficients[j] = 0.0 ;
    		else
    			{
    			Coefficients[j] = (double)Factorial(n+j) / (double)(Factorial((n+j)/2) * Factorial((n-j)/2) * Factorial(j)) ;
    			Coefficients[j] = Math.pow(-1.0, (int)((n-j)/2)) * Coefficients[j] / Math.pow(2.0, n) ;
    			}
    	}
     
     
     
    /** Methode qui calcule recursivement le factoriel du nombre passe en argument.
     * @param x Le nombre dont on veut le factoriel.
     * @return Le factoriel.*/
    protected int Factorial(int x)
    	{
    	if ( x < 0 ) throw new IllegalArgumentException("Negative number (Stupid mathematician or weak computer scientist)!") ; // Pour les neuneux des maths.
    	if ( x == 0 ) return 1 ;
    	return x*Factorial(x-1) ;
    	}
     
    }




    Le calcul des moments.
    Ici aussi, ne garder que la méthode compute si vous souhaitez aller à l'essentiel.
    Remplacer l'erreur "ImageBadTypeColorError" par une simple "Error".
    Code java :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
     
    import imageTiTi.ImageTools;
     
    import java.awt.image.BufferedImage;
    import java.awt.image.WritableRaster;
    import java.io.IOException;
     
    /**
     * <p>Description: Cette classe calcule les moments de Legendre d'une forme.</p>
     * <p>Sources : <html>http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/SHUTLER3/node10.html</html>.</p>
     * <p>Package(s) required: imageTiTi.</p>
     * <p>Copyright: Copyright (c) 2007-2011.</p>
     * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
     * <p>Updates:<br>
     * 21 Avril 2009 => Creation.</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class Legendre
    {
     
    /** Ordre du polynome.*/
    protected int Order = -1 ;
     
    /** Le polynome de Legendre Pm(x).*/
    protected LegendrePolynomial[] Pm = null ;
    /** Le polynome de Legendre Pn(y).*/
    protected LegendrePolynomial[] Pn = null ;
     
    /** Tableau qui contient les resultats (les valeurs des moments).*/
    protected double[][] LegendreMoments = null ;
     
     
     
    public Legendre()
    	{
    	}
     
     
     
     
    /** Methode qui lance le calcul des moments sur des images binaires.
     * @param image L'image contenant la forme.
     * @param Order L'ordre maximum a calculer.*/
    public void Compute(BufferedImage image, int Order)
    	{
    	if ( ImageTools.isColored(image) ) throw new IllegalArgumentException("Only binary or gray level image supported.") ;
    	if ( Order < 1 ) throw new Error("Order < 1.") ;
    	int m, n, x, y, Surface ;
    	int height = image.getHeight() ;
    	int width = image.getWidth() ;
    	double Value ;
    	WritableRaster wr = image.getRaster() ;
     
    	if ( Order != this.Order ) // Pour éviter de tout recalculer à chaque fois.
    		{
    		this.Order = Order ;
     
    		Pm = null ;
    		Pn = null ;
    		Pm = new LegendrePolynomial[Order+1] ;
    		Pn = new LegendrePolynomial[Order+1] ;
    		for (n=0 ; n <= Order ; n++)
    			{
    			Pm[n] = new LegendrePolynomial(n) ;
    			Pn[n] = new LegendrePolynomial(n) ;
    			}
     
    		LegendreMoments = null ;
    		LegendreMoments = new double[Order+1][Order+1] ;
    		}
     
    	Surface = 0 ;
    	for (m=0 ; m <= Order ; m++)
    		for (n=0 ; n <= Order ; n++)
    			if ( m+n <= Order )
    				{
    				Value = 0.0 ;
    				for (y=0 ; y < height ; y++)
    					for (x=0 ; x < width ; x++)
    						if ( wr.getSample(x, y, 0) > 0 )
    							{
    							Value += Pm[m].Value(x) * Pn[n].Value(y) ; 
    							Surface++ ;
    							}
    				LegendreMoments[m][n] = (2.0*m+1) * (2.0*n+1) / (double)Surface * Value  ;
    				}
     
    	wr = null ;
    	}
     
     
     
     
     
     
     
     
     
     
     
    /* ------------------------------------------------------- Les getters ------------------------------------------------------- */
    public double[][] getLegendreMoments()
    	{
    	return LegendreMoments ;
    	}
     
     
    public double getLegendreMoments(int m, int n)
    	{
    	return LegendreMoments[m][n] ;
    	}
     
     
     
     
    /** Methode qui retourne les noms des moments calcules lors des derniers resultats.
     * @return Les noms des moments.*/
    public String LastNames()
    	{
    	return LastNames(" ") ;
    	}
     
     
    /** Methode qui retourne les noms des moments calcules lors des derniers resultats.
     * @param Separator Le separateur a utiliser.
     * @return La chaine de caractere contenant les noms.*/
    public String LastNames(String Separator)
    	{
    	StringBuffer sb = new StringBuffer() ;
    	for (int m=0 ; m <= Order ; m++)
    		for (int n=0 ; n <= Order ; n++)
    			if ( m+n <= Order )
    				sb.append(m + "-" + n).append(Separator) ;
    	return sb.toString() ;
    	}
     
     
    /** Methode qui affiche les noms des moments calcules lors des derniers resultats.*/
    public void DisplayLastNames()
    	{
    	DisplayLastNames(" ") ;
    	}
     
     
    /** Methode qui affiche les noms des moments calcules lors des derniers resultats.
     * @param Separator Le separateur a utiliser.*/
    public void DisplayLastNames(String Separator)
    	{
    	System.out.println(LastNames(Separator)) ;
    	}
     
     
    /** Methode qui affiche les derniers resultats.*/
    public void DisplayLast()
    	{
    	System.out.println(toString()) ;
    	}
     
     
    /** Methode qui affiche les derniers resultats.
     * @param Separator Le separateur a utiliser.*/
    public void DisplayLast(String Separator)
    	{
    	System.out.println(toString(Separator)) ;
    	}
     
     
    /** Methode qui ecrit les derniers resultats dans un objet de type Appendable.
     * @param out L'objet qui doit implementer l'interface Appendable.*/
    public void appendTo(Appendable out)
    	{
    	appendTo(out, " ") ;
    	}
     
     
    /** Methode qui ecrit les derniers resultats dans un objet de type Appendable.
     * @param out L'objet qui doit implementer l'interface Appendable.
     * @param Separator Le separateur a utiliser.*/
    public void appendTo(Appendable out, String Separator)
    	{
    	try	{
    		for (int m=0 ; m <= Order ; m++)
    			for (int n=0 ; n <= Order ; n++)
    				if ( m+n <= Order )
    					out.append(String.valueOf(LegendreMoments[m][n])).append(Separator) ;
    		}
    	catch ( IOException e )
    		{
    		e.printStackTrace() ;
    		throw new Error("Exception levée.") ;
    		}
    	}
     
     
    /** On surcharge la methode pour qu'elle renvoit les derniers resultats.
     * @return Les resultats sous forme de chaines.*/
    public String toString()
    	{
    	return toString(" ") ;
    	}
     
     
    /** On surcharge la methode pour qu'elle renvoit les derniers resultats.
     * @param Separator Le separateur a utiliser.
     * @return Les resultats sous forme de chaines.*/
    public String toString(String Separator)
    	{
    	StringBuilder sb = new StringBuilder() ;
    	this.appendTo(sb) ;
    	return sb.toString() ;
    	}
     
    }
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  5. #5
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut Mise à jour et stockage dans les archives DVP

    Bonsoir,

    voici le lien vers la version archive du forum : http://java.developpez.com/telecharg...d/1656/Moments
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  6. #6
    Membre régulier Avatar de miss_angel
    Inscrit en
    février 2008
    Messages
    206
    Détails du profil
    Informations forums :
    Inscription : février 2008
    Messages : 206
    Points : 71
    Points
    71

    Par défaut

    Citation Envoyé par ToTo13 Voir le message
    Voilà deux classes permettant de calculer les moments de Legendre. La première calcule le polynôme de Legendre et la deuxième utilise la première pour en calculer les moments.

    Remarque : le "extends" peut être supprimé car c'est une extension d'une classes Polynomial 'générique' que j'utilise de temps en temps pour modéliser des polynômes.


    Code java :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    import mathematics.functions.Polynomial;
     
    /**
     * <p>Description : Cette classe represente le polynome de Legendre. Une simple extension de la classe Polynom a laquelle on ajoute le calcul des coefficients.</p>
     * <p>Package necessaires : mathematics.</p>
     * <p>Dernieres modifications :<br>
     * 21 Avril 2009 => Creation.</p>
     * <p>Copyright : Copyright (c) 2007.</p>
     * <p>Laboratoire : LSIS.</p>
     * <p>Equipe : Image et Modele, I&M (ex LXAO).</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class LegendrePolynomial extends Polynomial
    {
     
    /** Un petit constructeur qui appelle le constructeur pere et lance le calcul des coefficients en fonction du degres du polynome.
     * @param Degres Le degres du polynome.*/
    public LegendrePolynomial(int Degres)
    	{
    	super(Degres) ;
    	ComputeCoefficients() ;
    	}
     
     
    /** Methode qui calcule les coefficient du polynome de Legendre.*/
    protected void ComputeCoefficients()
    	{
    	int n = Degres ;
     
    	for (int j=0 ; j <= n ; j++)
    		if ( Math.abs(n-j) % 2 != 0 ) Coefficients[j] = 0.0 ;
    		else
    			{
    			Coefficients[j] = (double)Factorial(n+j) / (double)(Factorial((n+j)/2) * Factorial((n-j)/2) * Factorial(j)) ;
    			Coefficients[j] = Math.pow(-1.0, (int)((n-j)/2)) * Coefficients[j] / Math.pow(2.0, n) ;
    			}
    	}
     
     
     
    /** Methode qui calcule recursivement le factoriel du nombre passe en argument.
     * @param x Le nombre dont on veut le factoriel.
     * @return Le factoriel.*/
    protected int Factorial(int x)
    	{
    	if ( x < 0 ) throw new IllegalArgumentException("Negative number (Stupid mathematician or weak computer scientist)!") ; // Pour les neuneux des maths.
    	if ( x == 0 ) return 1 ;
    	return x*Factorial(x-1) ;
    	}
     
    }




    Le calcul des moments.
    Ici aussi, ne garder que la méthode compute si vous souhaitez aller à l'essentiel.
    Remplacer l'erreur "ImageBadTypeColorError" par une simple "Error".
    Code java :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
     
    import imageTiTi.ImageTools;
     
    import java.awt.image.BufferedImage;
    import java.awt.image.WritableRaster;
    import java.io.IOException;
     
    /**
     * <p>Description: Cette classe calcule les moments de Legendre d'une forme.</p>
     * <p>Sources : <html>http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/SHUTLER3/node10.html</html>.</p>
     * <p>Package(s) required: imageTiTi.</p>
     * <p>Copyright: Copyright (c) 2007-2011.</p>
     * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
     * <p>Updates:<br>
     * 21 Avril 2009 => Creation.</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class Legendre
    {
     
    /** Ordre du polynome.*/
    protected int Order = -1 ;
     
    /** Le polynome de Legendre Pm(x).*/
    protected LegendrePolynomial[] Pm = null ;
    /** Le polynome de Legendre Pn(y).*/
    protected LegendrePolynomial[] Pn = null ;
     
    /** Tableau qui contient les resultats (les valeurs des moments).*/
    protected double[][] LegendreMoments = null ;
     
     
     
    public Legendre()
    	{
    	}
     
     
     
     
    /** Methode qui lance le calcul des moments sur des images binaires.
     * @param image L'image contenant la forme.
     * @param Order L'ordre maximum a calculer.*/
    public void Compute(BufferedImage image, int Order)
    	{
    	if ( ImageTools.isColored(image) ) throw new IllegalArgumentException("Only binary or gray level image supported.") ;
    	if ( Order < 1 ) throw new Error("Order < 1.") ;
    	int m, n, x, y, Surface ;
    	int height = image.getHeight() ;
    	int width = image.getWidth() ;
    	double Value ;
    	WritableRaster wr = image.getRaster() ;
     
    	if ( Order != this.Order ) // Pour éviter de tout recalculer à chaque fois.
    		{
    		this.Order = Order ;
     
    		Pm = null ;
    		Pn = null ;
    		Pm = new LegendrePolynomial[Order+1] ;
    		Pn = new LegendrePolynomial[Order+1] ;
    		for (n=0 ; n <= Order ; n++)
    			{
    			Pm[n] = new LegendrePolynomial(n) ;
    			Pn[n] = new LegendrePolynomial(n) ;
    			}
     
    		LegendreMoments = null ;
    		LegendreMoments = new double[Order+1][Order+1] ;
    		}
     
    	Surface = 0 ;
    	for (m=0 ; m <= Order ; m++)
    		for (n=0 ; n <= Order ; n++)
    			if ( m+n <= Order )
    				{
    				Value = 0.0 ;
    				for (y=0 ; y < height ; y++)
    					for (x=0 ; x < width ; x++)
    						if ( wr.getSample(x, y, 0) > 0 )
    							{
    							Value += Pm[m].Value(x) * Pn[n].Value(y) ; 
    							Surface++ ;
    							}
    				LegendreMoments[m][n] = (2.0*m+1) * (2.0*n+1) / (double)Surface * Value  ;
    				}
     
    	wr = null ;
    	}
     
     
     
     
     
     
     
     
     
     
     
    /* ------------------------------------------------------- Les getters ------------------------------------------------------- */
    public double[][] getLegendreMoments()
    	{
    	return LegendreMoments ;
    	}
     
     
    public double getLegendreMoments(int m, int n)
    	{
    	return LegendreMoments[m][n] ;
    	}
     
     
     
     
    /** Methode qui retourne les noms des moments calcules lors des derniers resultats.
     * @return Les noms des moments.*/
    public String LastNames()
    	{
    	return LastNames(" ") ;
    	}
     
     
    /** Methode qui retourne les noms des moments calcules lors des derniers resultats.
     * @param Separator Le separateur a utiliser.
     * @return La chaine de caractere contenant les noms.*/
    public String LastNames(String Separator)
    	{
    	StringBuffer sb = new StringBuffer() ;
    	for (int m=0 ; m <= Order ; m++)
    		for (int n=0 ; n <= Order ; n++)
    			if ( m+n <= Order )
    				sb.append(m + "-" + n).append(Separator) ;
    	return sb.toString() ;
    	}
     
     
    /** Methode qui affiche les noms des moments calcules lors des derniers resultats.*/
    public void DisplayLastNames()
    	{
    	DisplayLastNames(" ") ;
    	}
     
     
    /** Methode qui affiche les noms des moments calcules lors des derniers resultats.
     * @param Separator Le separateur a utiliser.*/
    public void DisplayLastNames(String Separator)
    	{
    	System.out.println(LastNames(Separator)) ;
    	}
     
     
    /** Methode qui affiche les derniers resultats.*/
    public void DisplayLast()
    	{
    	System.out.println(toString()) ;
    	}
     
     
    /** Methode qui affiche les derniers resultats.
     * @param Separator Le separateur a utiliser.*/
    public void DisplayLast(String Separator)
    	{
    	System.out.println(toString(Separator)) ;
    	}
     
     
    /** Methode qui ecrit les derniers resultats dans un objet de type Appendable.
     * @param out L'objet qui doit implementer l'interface Appendable.*/
    public void appendTo(Appendable out)
    	{
    	appendTo(out, " ") ;
    	}
     
     
    /** Methode qui ecrit les derniers resultats dans un objet de type Appendable.
     * @param out L'objet qui doit implementer l'interface Appendable.
     * @param Separator Le separateur a utiliser.*/
    public void appendTo(Appendable out, String Separator)
    	{
    	try	{
    		for (int m=0 ; m <= Order ; m++)
    			for (int n=0 ; n <= Order ; n++)
    				if ( m+n <= Order )
    					out.append(String.valueOf(LegendreMoments[m][n])).append(Separator) ;
    		}
    	catch ( IOException e )
    		{
    		e.printStackTrace() ;
    		throw new Error("Exception levée.") ;
    		}
    	}
     
     
    /** On surcharge la methode pour qu'elle renvoit les derniers resultats.
     * @return Les resultats sous forme de chaines.*/
    public String toString()
    	{
    	return toString(" ") ;
    	}
     
     
    /** On surcharge la methode pour qu'elle renvoit les derniers resultats.
     * @param Separator Le separateur a utiliser.
     * @return Les resultats sous forme de chaines.*/
    public String toString(String Separator)
    	{
    	StringBuilder sb = new StringBuilder() ;
    	this.appendTo(sb) ;
    	return sb.toString() ;
    	}
     
    }
    Bonjour Toto
    J'essaie de convertir le code en C++ et j'ai du mal à comprendre cette ligne de code:
    Value += Pm[m].Value(x) * Pn[n].Value(y) ;
    Selon la formule de calcul de LegendreMoment[m][n], Pm[m]devrait être multiplier par (x) exposant (m), idem Pn[n] multiplier par (y) exposant (n). Sinon je vois pas le sens de Pm[m].value(x)?? est ce que value est une fonction prédéfinie que je vois pas?

    Merci de m'éclairer ces points
    Il faut laisser du temps au temps...

  7. #7
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut

    Oulala... c'est que ce code n'est plus très jeune...

    J'ai utilisé les formules décrites ici.

    Cela calcule la valeur pour 'x' du mième polynôme Pm.
    Donc le calcul de puissance est faite directement dans le polynôme, avec multiplication par le coefficient de Legendre correspondant.

    En revanche, dans cette version, comme je travaille sur des formes binaires, je ne multiplie pas par la valeur du pixel, mais je fais un test (pixel nul ou non).

    Est ce que cela semble plus clair ?
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  8. #8
    Membre régulier Avatar de miss_angel
    Inscrit en
    février 2008
    Messages
    206
    Détails du profil
    Informations forums :
    Inscription : février 2008
    Messages : 206
    Points : 71
    Points
    71

    Par défaut

    Citation Envoyé par ToTo13 Voir le message
    Oulala... c'est que ce code n'est plus très jeune...

    J'ai utilisé les formules décrites ici.

    Cela calcule la valeur pour 'x' du mième polynôme Pm.
    Donc le calcul de puissance est faite directement dans le polynôme, avec multiplication par le coefficient de Legendre correspondant.

    En revanche, dans cette version, comme je travaille sur des formes binaires, je ne multiplie pas par la valeur du pixel, mais je fais un test (pixel nul ou non).

    Est ce que cela semble plus clair ?
    Merci pour la réponse
    En fait moi je travaille sur une image de niveau de gris du coup j'ai besoin de calculer pour tous les pixels. Est ce que dans ce cas je peux multiplier avec x exposant(m) ou il suffit de virer le test "if ( wr.getSample(x, y, 0) > 0 )" pour que ça tourne pour le cas de niveau de gris??
    Aussi ce qui cloche pour moi c'est .Value(x), je comprends pas d'où viens et je la trouve pas: est ce que c'est un attribut ou une fonction prédéfinie dans la classe "LegendrePolynomial" ? Parce que Pm[m] est un tableau de coefficients de type double.
    Merci de m'éclaircir ce point
    Il faut laisser du temps au temps...

  9. #9
    Modérateur
    Avatar de ToTo13
    Homme Profil pro Guillaume
    Ingénieur de Recherche
    Inscrit en
    janvier 2006
    Messages
    5 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Guillaume
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Santé

    Informations forums :
    Inscription : janvier 2006
    Messages : 5 188
    Points : 8 118
    Points
    8 118

    Par défaut

    Citation Envoyé par miss_angel Voir le message
    En fait moi je travaille sur une image de niveau de gris du coup j'ai besoin de calculer pour tous les pixels. Est ce que dans ce cas je peux multiplier avec x exposant(m) ou il suffit de virer le test "if ( wr.getSample(x, y, 0) > 0 )" pour que ça tourne pour le cas de niveau de gris??
    Il faut effectivement supprimer ce test, puis (d'après la formule dans le lien) multiplier par la valeur du pixel.


    Citation Envoyé par miss_angel Voir le message
    Aussi ce qui cloche pour moi c'est .Value(x), je comprends pas d'où viens et je la trouve pas: est ce que c'est un attribut ou une fonction prédéfinie dans la classe "LegendrePolynomial" ? Parce que Pm[m] est un tableau de coefficients de type double.
    Ben non justement, Pm et Pn sont des tableaux de LegendrePolynomial. Ce sont donc des polynômes.
    Et lorsque j'appelle ".Value(x)", je calcule la valeur du polynôme en 'x'.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  10. #10
    Membre régulier Avatar de miss_angel
    Inscrit en
    février 2008
    Messages
    206
    Détails du profil
    Informations forums :
    Inscription : février 2008
    Messages : 206
    Points : 71
    Points
    71

    Par défaut

    Merci bien Cher Toto
    Il faut laisser du temps au temps...

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •