IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

[image] Snake (contour actif)


Sujet :

Contribuez

  1. #1
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut [image] Snake (contour actif)
    Voici une implémentation Java de l'algorithme "Snake" (contour actif).

    L'algorithme Snake permet de tracer le contour d'une zone irrégulière en déformant progressivement une courbe de départ. Pour plus d'informations, je vous conseille l'article de khayyam90.




    La classe Snake (attributs+constructeur)
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public class Snake {
     
    	// Points of the snake
    	private List<Point> snake;
     
    	// Length of the snake (euclidean distance)
    	private double snakelength=0;
     
    	// size of the image (and of the 2 arrays below)
    	private int width=0,height=0;
     
    	// gradient value (modulus)
    	private int[][] gradient;
     
    	// gradient flow (modulus)
    	private int[][] flow;
     
    	// 3x3 neighborhood used to compute energies
    	private double[][] e_uniformity = new double[3][3];
    	private double[][] e_curvature  = new double[3][3];
    	private double[][] e_flow       = new double[3][3];
    	private double[][] e_inertia    = new double[3][3];
     
    	// auto add/remove points to the snake
    	// according to distance between points
    	private boolean AUTOADAPT=true;
    	private static int AUTOADAPT_LOOP=10;
    	private static int AUTOADAPT_MINLEN=8;
    	private static int AUTOADAPT_MAXLEN=16;
     
    	// maximum number of iterations (if no convergence)
    	private static int MAXITERATION = 1000;
     
    	// coefficients for the 4 energy functions
    	public double alpha=1.1, beta=1.2, gamma=1.5, delta=3.0;
     
    	// alpha = coefficient for uniformity (high => force equals distance between points)
    	// beta  = coefficient for curvature  (high => force smooth curvature)
    	// gamma  = coefficient for flow      (high => force gradient attraction)
    	// delta  = coefficient for intertia  (high => get stuck to gradient)
     
    	/**
             * Constructor
             *
             * @param width,height size of the image and of the 2 following arrays
             * @param gradient gradient (modulus)
             * @param flow gradient flow (modulus)
             * @param points inital points of the snake
             */
    	public Snake(int width, int height, int[][] gradient, int[][] flow, Point... points) {
    		this.snake = new ArrayList<Point>(Arrays.asList(points));
    		this.gradient = gradient;
    		this.flow = flow;
    		this.width = width;
    		this.height = height;
    	}
     
     
    	// add here the other methods.
     
    }

    Les méthodes de l'algorithme "snake"
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    /**
     * main loop
     * 
     * @return the final snake
     */
    public List<Point> loop() {
    	int loop=0;
     
    	while(step() && loop<MAXITERATION) {
    		// auto adapt the number of points in the snake
    		if (AUTOADAPT && (loop%AUTOADAPT_LOOP)==0) {
    			removeOverlappingPoints(AUTOADAPT_MINLEN);
    			addMissingPoints(AUTOADAPT_MAXLEN);
    		}
    		loop++;
    	}
     
    	// rebuild using spline interpolation
    	if (AUTOADAPT) rebuild(AUTOADAPT_MAXLEN);
     
    	return this.snake;
    }
     
    /**
     * update the position of each point of the snake
     *
     * @return true if the snake has changed, otherwise false.
     */
    private boolean step() {
    	boolean changed=false;
    	Point p = new Point(0,0);
     
    	// compute length of original snake (used by method: f_uniformity)
    	this.snakelength = getsnakelength();
     
    	// compute the new snake
    	List<Point> newsnake = new ArrayList<Point>(snake.size());
     
    	// for each point of the previous snake
    	for(int i=0;i<snake.size();i++) {
    		Point prev = snake.get((i+snake.size()-1)%snake.size());
    		Point cur  = snake.get(i);
    		Point next = snake.get((i+1)%snake.size());
     
    		// compute all energies
    		for(int dy=-1;dy<=1;dy++) {
    			for(int dx=-1;dx<=1;dx++) {
    				p.setLocation(cur.x+dx, cur.y+dy);
    				e_uniformity[1+dx][1+dy] = f_uniformity(prev,next,p);
    				e_curvature[1+dx][1+dy]  = f_curvature(prev,p,next);
    				e_flow[1+dx][1+dy]       = f_gflow(cur,p);
    				e_inertia[1+dx][1+dy]    = f_inertia(cur,p);
    			}
    		}
     
    		// normalize energies
    		normalize(e_uniformity);
    		normalize(e_curvature);
    		normalize(e_flow);
    		normalize(e_inertia);
     
    		// find the point with the minimum sum of energies
    		double emin = Double.MAX_VALUE, e=0;
    		int x=0,y=0;
    		for(int dy=-1;dy<=1;dy++) {
    			for(int dx=-1;dx<=1;dx++) {
    				e = 0;
    				e+= alpha * e_uniformity[1+dx][1+dy]; // internal energy
    				e+= beta  * e_curvature[1+dx][1+dy];  // internal energy
    				e+= gamma * e_flow[1+dx][1+dy];       // external energy
    				e+= delta * e_inertia[1+dx][1+dy];    // external energy
     
    				if (e<emin) { emin=e; x=cur.x+dx; y=cur.y+dy; }
    			}
    		}
     
    		// boundary check
    		if (x<1) x=1;
    		if (x>=(this.width-1)) x=this.width-2;
    		if (y<1) y=1;
    		if (y>=(this.height-1)) y=this.height-2;
     
    		// compute the returned value
    		if (x!=cur.x || y!=cur.y) changed=true;
     
    		// create the point in the new snake
    		newsnake.add(new Point(x,y));
    	}
     
    	// new snake becomes current
    	this.snake=newsnake;
     
    	return changed;
    }
     
    // normalize energy matrix
    private void normalize(double[][] array3x3) {
    	double sum=0;
    	for(int i=0;i<3;i++)
    		for(int j=0;j<3;j++)
    			sum+=Math.abs(array3x3[i][j]);
     
    	if (sum==0) return;
     
    	for(int i=0;i<3;i++)
    		for(int j=0;j<3;j++)
    			array3x3[i][j]/=sum;
    }
     
    private double getsnakelength() {
    	// total length of snake
    	double length=0;
    	for(int i=0;i<snake.size();i++) {
    		Point cur   = snake.get(i);
    		Point next  = snake.get((i+1)%snake.size());
    		length+=distance2D(cur, next);
    	}
    	return length;
    }
     
    private double distance2D(Point A, Point B) {
    	int ux = A.x-B.x;
    	int uy = A.y-B.y;
    	double un = ux*ux+uy*uy;
    	return Math.sqrt(un);
    }

    Les méthodes des fonctions d'energie:
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    private double f_uniformity(Point prev, Point next, Point p) {
     
    	// length of previous segment
    	double un = distance2D(prev, p);
     
    	// mesure of uniformity
    	double avg = snakelength/snake.size();
    	double dun = Math.abs(un-avg);
     
    	// elasticity energy
    	return dun*dun;
    }
     
    private double f_curvature(Point prev, Point p, Point next) {
    	int ux = p.x-prev.x;
    	int uy = p.y-prev.y;
    	double un = Math.sqrt(ux*ux+uy*uy);
     
    	int vx = p.x-next.x;
    	int vy = p.y-next.y;
    	double vn = Math.sqrt(vx*vx+vy*vy);
     
    	if (un==0 || vn==0) return 0;
     
    	double cx = (vx+ux)/(un*vn);
    	double cy = (vy+uy)/(un*vn);
     
    	// curvature energy
    	double cn = cx*cx+cy*cy;
    	return cn;
    }
     
    private double f_gflow(Point cur, Point p) {
    	// gradient flow
    	int dcur = this.flow[cur.x][cur.y];
    	int dp   = this.flow[p.x][p.y];
    	double d = dp-dcur;
    	return d;
    }
     
    private double f_inertia(Point cur, Point p) {
    	double d = distance2D(cur, p);
    	double g = this.gradient[cur.x][cur.y];
    	double e = g*d;
    	return e;
    }

    Les méthodes du mécanisme d'auto-adaptation:
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    // rebuild the snake using cubic spline interpolation
    private void rebuild(int space) {
     
    	// precompute length(i) = length of the snake from start to point #i
    	double[] clength = new double[snake.size()+1];
    	clength[0]=0;
    	for(int i=0;i<snake.size();i++) {
    		Point cur   = snake.get(i);
    		Point next  = snake.get((i+1)%snake.size());
    		clength[i+1]=clength[i]+distance2D(cur, next);
    	}
     
    	// compute number of points in the new snake
    	double total = clength[snake.size()];
    	int nmb = (int)(0.5+total/space);
     
    	// build a new snake
    	List<Point> newsnake = new ArrayList<Point>(snake.size());
    	for(int i=0,j=0;j<nmb;j++) {
    		// current length in the new snake
    		double dist = (j*total)/nmb;
     
    		// find corresponding interval of points in the original snake
    		while(! (clength[i]<=dist && dist<clength[i+1])) i++;
     
    		// get points (P-1,P,P+1,P+2) in the original snake
    		Point prev  = snake.get((i+snake.size()-1)%snake.size());
    		Point cur   = snake.get(i);
    		Point next  = snake.get((i+1)%snake.size());
    		Point next2  = snake.get((i+2)%snake.size());
     
    		// do cubic spline interpolation
    		double t =  (dist-clength[i])/(clength[i+1]-clength[i]);
    		double t2 = t*t, t3=t2*t;
    		double c0 =  1*t3;
    		double c1 = -3*t3 +3*t2 +3*t + 1;
    		double c2 =  3*t3 -6*t2 + 4;
    		double c3 = -1*t3 +3*t2 -3*t + 1;
    		double x = prev.x*c3 + cur.x*c2 + next.x* c1 + next2.x*c0;
    		double y = prev.y*c3 + cur.y*c2 + next.y* c1 + next2.y*c0;
    		Point newpoint = new Point( (int)(0.5+x/6), (int)(0.5+y/6) );
     
    		// add computed point to the new snake
    		newsnake.add(newpoint);
    	}
    	this.snake = newsnake;
    }
     
     
    private void removeOverlappingPoints(int minlen) {
    	// for each point of the snake
    	for(int i=0;i<snake.size();i++) {
    		Point cur = snake.get(i);
     
    		// check the other points (right half)
    		for(int di=1+snake.size()/2;di>0;di--) {
    			Point end  = snake.get((i+di)%snake.size());
    			double dist = distance2D(cur,end);
     
    			// if the two points are to close...
    			if ( dist>minlen ) continue;
     
    			// ... cut the "loop" part og the snake
    			for(int k=0;k<di;k++) snake.remove( (i+1) %snake.size() );
    			break;
    		}
    	}
    }
     
    private void addMissingPoints(int maxlen) {
    	// for each point of the snake
    	for(int i=0;i<snake.size();i++) {
    		Point prev  = snake.get((i+snake.size()-1)%snake.size());
    		Point cur   = snake.get(i);
    		Point next  = snake.get((i+1)%snake.size());
    		Point next2  = snake.get((i+2)%snake.size());
     
    		// if the next point is to far then add a new point
    		if ( distance2D(cur,next)>maxlen ) {
     
    			// precomputed Uniform cubic B-spline for t=0.5
    			double c0=0.125/6.0, c1=2.875/6.0, c2=2.875/6.0, c3=0.125/6.0;
    			double x = prev.x*c3 + cur.x*c2 + next.x* c1 + next2.x*c0;
    			double y = prev.y*c3 + cur.y*c2 + next.y* c1 + next2.y*c0;
    			Point newpoint = new Point( (int)(0.5+x), (int)(0.5+y) );
     
    			snake.add( i+1 , newpoint ); i--;
    		}
    	}
    }


    Utilisation:

    Le constructeur de la classe Snake a besoin des paramètres suivants:

    • int width,height: la taille de l'image (et des deux tableaux suivants)
    • int[][] gradient: un tableau contenant la norme du gradient pour chaque pixel [x][y]
    • int[][] flow: un tableau contenant la norme du vecteur de flux pour chaque pixel [x][y].
      En pratique, on peut utiliser la carte des distances jusqu'au pic de gradient le plus proche
    • Point... points: la liste des points constituant le snake initial


    La méthode publique "loop()" fait évoluer le snake jusqu'a convergence et retourne la liste des points du snake final.

  2. #2
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    L'implémentation sous forme d'un JAR executable: snake.jar


  3. #3
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Bonjour,
    Tout d'abord merci PseudoCode pour cette contribution,c'est exactement ce que je cherchais...
    J'essais d'implémenter cette algorithme en utilisant C++ Builder.
    Mais je ne suis pas arrivé à comprendre la procédure f_gflow
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private double f_gflow(Point cur, Point p) {
        // gradient flow
        int dcur = this.flow[cur.x][cur.y];
        int dp   = this.flow[p.x][p.y];
        double d = dp-dcur;
        return d;
    }
    Que représente flow, est ce la carte des distances de l'image du gradient binarisée ?


    -Concernant la fonction gradient(i,j),je l'ai implémenter de cette façon :
    gradient(i,j)=sqrt(gradientX(i,j)²+gradientY(i,j)²)
    Tq:

    gradientX(i,j)=ABS(valeur_pixel(i+1,j)-valeur_pixel(i-1,j))
    &
    gradientY(i,j)=ABS(valeur_pixel(i,j+1)-valeur_pixel(i,j-1))

    Est ce la bonne méthode de calcul du gradient?!

  4. #4
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par b_reda31 Voir le message
    Bonjour,
    Tout d'abord merci PseudoCode pour cette contribution,c'est exactement ce que je cherchais...
    Heureux que cela serve à quelqu'un. J'en profite pour citer ici l'article de khayyam90 qui sert de support à cette contribution.

    Que représente flow, est ce la carte des distances de l'image du gradient binarisée ?
    oui, c'est exactement cela.

    -Concernant la fonction gradient(i,j),je l'ai implémenter de cette façon :
    gradient(i,j)=sqrt(gradientX(i,j)²+gradientY(i,j)²)
    Tq:

    gradientX(i,j)=ABS(valeur_pixel(i+1,j)-valeur_pixel(i-1,j))
    &
    gradientY(i,j)=ABS(valeur_pixel(i,j+1)-valeur_pixel(i,j-1))

    Est ce la bonne méthode de calcul du gradient?!
    C'est une définition qui en vaut une autre. Personnellement j'utilise plutôt un noyau SOBEL ou MDIF, mais c'est une question d'habitude.

  5. #5
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    Heureux que cela serve à quelqu'un. J'en profite pour citer ici l'article de khayyam90 qui sert de support à cette contribution.
    J'ai lu dans cet article (II-4 Paragraphe 3)que le nombre de points dans le snake peut augmenter selon la taille du snake !!

    à quel moment et comment ajoute t on un point?

    PS:Je ne sais pas si je suis au bon endroit pour poser cette question,si ce n'est pas le cas je m'en excuse...

  6. #6
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par b_reda31 Voir le message
    J'ai lu dans cet article (II-4 Paragraphe 3)que le nombre de points dans le snake peut augmenter selon la taille du snake !!

    à quel moment et comment ajoute t on un point?
    Dans la boucle principale "loop()", si le mode auto-adaptation est activé (AUTOADAPT=true) alors on vérifie la forme du snake toutes les N itérations (N = AUTOADAPT_LOOP).

    L'auto-adaptation est composée de 2 phases:
    - Si 2 points sont trop près: suppression de l'un des 2 ( méthode removeOverlappingPoints() )
    - Si 2 points sont trop éloignés: ajouts de points entre les 2 ( méthode addMissingPoints() )

  7. #7
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Je m'y connais pas dutout en langage Java donc merci pour ces explications .
    Citation Envoyé par pseudocode Voir le message
    Dans la boucle principale "loop()", si le mode auto-adaptation est activé (AUTOADAPT=true) alors on vérifie la forme du snake toutyes les N itérations (N = AUTOADAPT_LOOP).
    Donc si je comprend bien,Si AUTOADAPT=False le nombre de points du snake restera fixe?
    Dans le cas contraire (AUTOADAPT=True),à chaque N itérations de l'algorithme je dois calculer pour chaque point du snake,la distance entre ce dernier et ses voisins (Successeur et prédécesseur),cette distance etant inférieure ou supérieure à un certain seuil (distance minimale,distance maximale respectivement),Je dois ajouter ou supprimer un point...
    Est ce bien ça la façon de procéder?!



    L'auto-adaptation est composée de 2 phases:
    - Si 2 points sont trop près: suppression de l'un des 2 ( méthode removeOverlappingPoints() )
    - Si 2 points sont trop éloignés: ajouts de points entre les 2 ( méthode addMissingPoints() )
    Encore une question :
    Concernant les valeurs de N(AUTODAPAT_LOOP),Distance minimale et maximale entre deux points.
    Comment choisir ces valeur?



    Merci encore.

    Cordialement.

  8. #8
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par b_reda31 Voir le message
    Donc si je comprend bien,Si AUTOADAPT=False le nombre de points du snake restera fixe?
    oui.

    Dans le cas contraire (AUTOADAPT=True),à chaque N itérations de l'algorithme je dois calculer pour chaque point du snake,la distance entre ce dernier et ses voisins (Successeur et prédécesseur),cette distance etant inférieure ou supérieure à un certain seuil (distance minimale,distance maximale respectivement),Je dois ajouter ou supprimer un point...
    Est ce bien ça la façon de procéder?!
    je ne sais pas si c'est "LA" façon de procéder, mais c'est celle que j'ai choisie.

    Encore une question :
    Concernant les valeurs de N(AUTODAPAT_LOOP),Distance minimale et maximale entre deux points.
    Comment choisir ces valeur?
    Généralement je choisis une valeur de Distancemin et je calcule "DistanceMax = 2 * DistanceMin", et "AUTODAPAT_LOOP = (Distance min + Distance max)/2".

    C'est totalement empirique mais ca me convient.

  9. #9
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Merci PseudoCode

  10. #10
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Décidement dés qu'un problème est résolu survient un autre!
    L'image Gradient+Flow que je réalise est differente de celle de l'application!

    Voici comment je la calcule:

    -Je calcule le gradient de l'image originale ("gradient.bmp").
    -Ensuite je binarise "gradient.bmp" en utilisant un seuil=100,j'obtient "gradientbinnaire.bmp".
    -A partir de "gradientbinnaire.bmp" je calcule la carte des distances et j'obtient "gradientflow.bmp".



    Et voici comment je calcule la carte des distances(a partir de "gradientbinnaire.bmp"):

    -Je mets les coordonnées de tous les points ayant 255 comme valeur dans un vecteur de point Contour[i].x,Contour[i].y.
    càd (Contour[i].x,Contour[i].y) sont les coordonnées du iéme point ayant la valeur 255 dans "gradientbinnaire.bmp"(Est ce clair?!)

    -Pour chaque point de l'image calculer la distance entre ce point et TOUS les point du vecteur Contour
    -La nouvelle valeur du point dans l'image sera la distance minimale,si cette valeur est supérieure à 255 elle prend 255.

    Est ce bien la méthode de calcul de la carte des distances?



    Rq:
    -Le traitement est relativement long!!
    -La distance entre deux point je la calcule de cette maniere : dist(A,B)=SQRT((Ax-Bx)²+(Ay-By)²)




    Voici les images que j'obtient,comme je l'ai déja dis elle sont differentes de celles de la contribution,Auriez vous une explication?

  11. #11
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par b_reda31 Voir le message
    -Pour chaque point de l'image calculer la distance entre ce point et TOUS les point du vecteur Contour
    -La nouvelle valeur du point dans l'image sera la distance minimale,si cette valeur est supérieure à 255 elle prend 255.

    Est ce bien la méthode de calcul de la carte des distances?
    Non, on ne doit pas limiter la valeur de la distance à "255". La valeur de la distance varie entre 0 et l'infinie, quoique dans le cas d'une image la plus grande distance possible est la diagonale = sqrt(largeur²+hauteur²) .

    -Le traitement est relativement long!!
    Il y a une méthode plus rapide: Carte des Distances (Chamfer)

    -La distance entre deux point je la calcule de cette maniere : dist(A,B)=SQRT((Ax-Bx)²+(Ay-By)²)
    Voici les images que j'obtient,comme je l'ai déja dis elle sont differentes de celles de la contribution,Auriez vous une explication?
    C'est juste que je n'utilise pas les meme couleurs.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if (gradient>seuil) {
    	rgb[0]=0; rgb[1]=gradient; rgb[2]=0;
    } else {
    	rgb[0]=Math.max(0,255-flow); rgb[1]=0; rgb[2]=0;					
    }

  12. #12
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    Non, on ne doit pas limiter la valeur de la distance à "255". La valeur de la distance varie entre 0 et l'infinie, quoique dans le cas d'une image la plus grande distance possible est la diagonale = sqrt(largeur²+hauteur²) .
    Cela concerne l'image dans laquelle l'algorithme se déroulera(Gradient+Flow)?

    Mais dans GradientFlow à afficher:
    Si la distance est supérieure à 255,la valeur du pixel depassera l'intervalle de couleur?!

    ça provoque des résultat pas trés jolis jolis chez moi!

  13. #13
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par b_reda31 Voir le message
    Cela concerne l'image dans laquelle l'algorithme se déroulera(Gradient+Flow)?
    oui.

    Mais dans GradientFlow à afficher:
    Si la distance est supérieure à 255,la valeur du pixel depassera l'intervalle de couleur?!
    ça provoque des résultat pas trés jolis jolis chez moi!
    Dans mon post précédent, tu remarqueras que la valeur du pixel pour le flow (en rouge) est limitée a l'intervalle 0-255:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    r=Math.max(0,255-flow); g=0; b=0;
    flow = 0 --> r = Math.max(0,255-0) = 255
    flow = +oo --> r = Math.max(0,255-infinity) = Math.max(0, -infinity) = 0

  14. #14
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Merci pour la rapidité de tes réponses .
    Je vais essayer de relire le code ligne par ligne.

  15. #15
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Si le fond était blanc au lieu de noir, ça marcherait plus trop ? (j'ai pas tout suivi)

    Je voyais l'algo comme un truc du genre :

    On génère une carte d'élévation du terrain (donc noir à 0 mètre et blanc à 100m par exemple), on entoure le truc d'une grande corde avec des roues, et les roues avance vers le milieu (si une pente est trop élevé (on peut voir ça en utilisant le gradient pour la direction du terrain et en regardant la pente à cet endroit), alors la roue s'arrête))

    A moins que tu ne considère que la valeur absolu de la pente, dans ce cas, il n'y a pas de soucis.

  16. #16
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par millie Voir le message
    On génère une carte d'élévation du terrain (donc noir à 0 mètre et blanc à 100m par exemple)
    On génère une carte d'élévation du GRADIENT du terrain.

  17. #17
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Bonjour,
    J'ai terminé l'implémentation de cet algorithme en utilisant les même méthodes d'énergie de cette contribution.
    J'ai essayé de faire quelque essais en jouant sur les différents parametres pour tester chaque énergie mais les résultats ne sont pas très encourageants
    J'ai fais quelques captures de mon application en ajoutant les différentes valeurs des parametres ainsi que le nombre d'itérations:


    Vous remarquerez que lorsque Beta est non nul,le snake se déplace bien vers les endroits de fort gradient mais il y a une force qui attire le coté droit du snake vers la droite!!

    J'ai pourtant implémenter la méthode CURVATURE de la même manière qu'il a été donnée dans la contribution !





    D'un autre coté en mettant Beta à 0 afin de tester la méthode UNIFORMITY,Le résultat est carrément chaotique!!


    Je vais continuer à vérifier mon code,si quelqu'un aurait une idée sur ce phénomène qu'il m'en fasse part svp...

  18. #18
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    hum... tu es sûr que ton "gradient vector flow" est bon ?

  19. #19
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Envoyé par pseudocode

    hum... tu es sûr que ton "gradient vector flow" est bon ?

    Apparement Oui puisque ça converge bien vers les point de fort gradient?!

    Je pense que le problème est dans l'énergie Interne.
    Je vais quand même revérifier tous ça.

  20. #20
    Membre éprouvé Avatar de b_reda31
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 899
    Points : 960
    Points
    960
    Par défaut
    Je ne sais pas si c'est le manque de sommeil ou autre chose,mais là tout commence à se chambouler dans ma tête

    Je vais essayer de résumer un peu la chose: (y a quelque chose qui cloche mais je ne sais pas ou)

    Nous avons l'image originale qui est à droite dans l'application JAR de cette contribution.

    Afin de déterminer l'énergie externe du snake il faut calculer la matrice FLOW qui est la la carte de distance normalisée du gradient binarisé de l'image originale....ouf
    Donc il faut tout d'abord calculer le gradient de l'image originale (Sobel par ex),ensuite binariser le gradient.

    à partir de gradient binaire il est donc possible de construire la carte de distance en utilisant un masque de chamfer selon cette contribution.
    A ce stade nous avons une carte de distance normalisée FLOW,qui est appelée dans cette méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private double f_gflow(Point cur, Point p) {
    	// gradient flow
    	int dcur = this.flow[cur.x][cur.y];
    	int dp   = this.flow[p.x][p.y];
    	double d = dp-dcur;
    	return d;
    }
    J'ai utilisé le masque chamfer3 (new int[] {1,0,3},new int[] {1,1,4}) donc pour normaliser j'ai diviser tous les elements de la matrice FLOW par 3.Et voici FLOW que j'ai obtenu après normalisation:


    Elle parait noir mais elle est juste trop sombre.



    Et si je ne normalise pas FLOW voici ce que j'obtiens :






    Envoyé par Pseudocode :






    Cela n'a rien à voir avec les résultats que j'ai obtenu.
    Aurais je fais une erreur quelque part?



    FLOW et GRADIENT+FLOW est ce la même chose?


    Merci d'avance pour vos réponses.

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/09/2012, 09h07
  2. Réponses: 1
    Dernier message: 06/05/2011, 17h16
  3. Snake : contours actifs
    Par gilsub dans le forum Traitement d'images
    Réponses: 5
    Dernier message: 24/04/2011, 14h15
  4. [Débutant] Snake (contour actif) pour les images
    Par ikrame dans le forum C++Builder
    Réponses: 2
    Dernier message: 07/01/2011, 12h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo