encore une toute dernière questions sur ce code...
Sur quelle théorie s'appuie le calcule de la courbure ? je n'arrive pas bien à saisir le sens des calculs..
Merci !
Oui, j'avoue que c'est assez étrange comme formule. Je ne me souviens plus trop comment j'en suis arrivé là, mais ca ne doit pas être très orthodoxe.
Ca ressemble à une dérivée seconde discrète, avec des points de sampling non uniforme.
http://fr.wikipedia.org/wiki/Dérivée_seconde_discrète
hehe merci !
Sinon je me disait aussi que l'énergie de courbure pouvait être approchée par la distance que fait le point par rapport au barycentre des points de son voisinage (donc le milieu du segment Pprev et Pnext dans le cas de la 2D). Mais il reste quelque chose qui me chiffonne dans cette faàon d'exprimer l'énergie de courbure : si le point P est situé sur le segment, mais pas au milieu, l'énergie de courbure voudra le faire déplacer vers le milieu du segment, alors que sa courbure sera nulle. Donc si elle est calculée comme ça, son effet accentuera l'effet de l'énergie de continuité, ce que je ne veux pas vraiment.
Oui, c'est vrai. Cette énergie n'est pas vraiment de la pure "courbure".
Au départ, si je me souviens bien, j'avais fait une énergie basée sur l'angle entre les 2 segments (enfin son cosinus, via le produit scalaire). Je ne sais pas trop pourquoi j'ai changé d'idée.
Sinon, il reste le 'vrai' calcul de la courbure : http://en.wikipedia.org/wiki/Curvatu...al_expressions
oki thanks !
je penserai a dresser une statue a ton effigie, ton code m'a beaucoup aidé ^^
Bonjour Pseudocode, je n'ai pas compris l'expression suivante qui était située dans la step() de ta contribution. Pourrais tu brievement me l'expliquer?
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 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; } } }
J'ai lu toutes la discussion et j'ai pas trouvé, ou c'est que j'ai des problèmes en java .
Merci d'avance pseudocode .
PS: Merci pour ta contribution m'a permis de mieux comprendre le fonctionnement des snakes et leurs implémentations.
(edit) Désolé, j'ai mal formulé ma question. Je voulais parler dans le code, à quoi correspond Double.MAX_VALUE?? Sinon tout est clair, j'ai compris les principes en majeure partie grâce à cette discussion.
Ah. C'est juste une astuce a deux balles pour initialiser la valeur de "emin" au premier passage dans la boucle.
Vu que "emin" est un type double, je n'ai pas de moyen de dire qu'il est "non initialisé" par défaut. En le forcant à une valeur "infinie", je suis sur que la première comparaison "if (e<emin)" sera vraie, et donc que emin sera initialisée avec la valeur de "e"
Ok, je vois.
Encore merci, pour la spontanéité de tes réponses et pour toutes les explications précedentes.
Bonjour Pseudocode,
Est ce que c'est possible de m'expliquer le choix de ces coefs (me donner un lien).
// 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;
j'ai vu partout sur le web, que pour une interpolation cubique, on utilise les points eux même pour déterminer ces 4 coefs d'un polynôme de degré 3.
Merci
Comme indiqué, ce sont les coefficients d'une B-splines cubique uniforme pour t=0.5
c0 = [0.5^3 0.5^2 0.5 1].1/6.[-1 3 -3 1] = (0.125*-1 + 0.25*3 + 0.5*-3 + 1)/6 = 0.125/6
c1 = [0.5^3 0.5^2 0.5 1].1/6.[3 -6 0 4] = (0.125*3 + 0.25*-6 + 0.5*0 + 4)/6 = 2.875/6
c2 = [0.5^3 0.5^2 0.5 1].1/6.[-3 3 3 1] = (0.125*-3 + 0.25*3 + 0.5*3 + 1)/6 = 2.875/6
c3 = [0.5^3 0.5^2 0.5 1].1/6.[1 0 0 0] = (0.125*1 + 0.25*0 + 0.5*0 + 0)/6 = 0.125/6
Bonjour,
J'ai testé le programme Snake que j'ai trouvé extrêmement intéressant pour mon application (approximation d'un contour par points, application en microscopie entra autres), bien plus simple (et largement suffisant) que des méthodes à base d'ondelettes.
Problème : si j'arrive à lire le code java, je suis au niveau 0 pour l'écriture.
J'ai essayé de le recharger sur Netbean, mais en vain.
Pour lancer cette application telle-quelle comme une procédure externe à mon application il faudrait que je puisse en plus :
1/ Passer le nom du fichier image en paramètre.
2/ Récupérer la liste des points dans un fichier texte.
3/ fermer Snake après écriture du fichier texte.
Cette modif est elle très complexe à ajouter ?
Qui pourrait m'aider éventuellement ?
merci d'avance
GF
Il faut créer un nouveau JAR en remplacant la classe "SnkeGUI" par une nouvelle classe qui gère les entrées/sorties depuis la ligne de commande.
Par exemple, un truc du genre:
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 public class SnakeCLI { public void process(String[] args) throws Exception { if (args.length<11) throw new Exception("usage: java -jar SnakeCLI.jar imagefile 25 1.0 1.0 1.0 1.0 true 10 8 16 300"); String FILENAME = args[0]; int THRESHOLD = Integer.parseInt(args[1]); // in % double ALPHA = Double.parseDouble(args[2]); double BETA = Double.parseDouble(args[3]); double GAMMA = Double.parseDouble(args[4]); double DELTA = Double.parseDouble(args[5]); boolean AUTOADAPT = Boolean.parseBoolean(args[6]); int AUTOADAPT_LOOP = Integer.parseInt(args[7]); int AUTOADAPT_MINLEN = Integer.parseInt(args[8]); int AUTOADAPT_MAXLEN = Integer.parseInt(args[9]); int MAXITERATION = Integer.parseInt(args[10]); // chargement de l'image BufferedImage image = loadimage(FILENAME); int W = image.getWidth(); int H = image.getHeight(); // calcul du gradient et du gradient-flow int[][] gradient = new int[W][H]; int[][] flow = new int[W][H]; computegflow(image, gradient, flow, THRESHOLD); // point initiaux du snake double radius = (W/2 + H/2) / 2; double perimeter = 6.28 * radius; int nmb = (int) (perimeter / 8); Point[] circle = new Point[nmb]; for (int i = 0; i < circle.length; i++) { double x = (W / 2 + 0) + (W / 2 - 2) * Math.cos((6.28 * i) / circle.length); double y = (H / 2 + 0) + (H / 2 - 2) * Math.sin((6.28 * i) / circle.length); circle[i] = new Point((int) x, (int) y); } // create snake instance Snake snake = new Snake(W, H, gradient, flow, circle); // snake base parameters snake.alpha = ALPHA; snake.beta = BETA; snake.gamma = GAMMA; snake.delta = DELTA; // snake extra parameters snake.AUTOADAPT = AUTOADAPT; snake.AUTOADAPT_LOOP = AUTOADAPT_LOOP; snake.AUTOADAPT_MINLEN = AUTOADAPT_MINLEN; snake.AUTOADAPT_MAXLEN = AUTOADAPT_MAXLEN; snake.MAXITERATION = MAXITERATION; // compute final snake int nmbloop = snake.loop(); if (nmbloop>=snake.MAXITERATION) throw new Exception("Snake does not converge!"); // print snake points to console for(Point p:snake.snake) System.out.printf("%d %d\n",p.x,p.y); } // Load the image to process private BufferedImage loadimage(String filename) throws Exception { File file = new File(filename); return ImageIO.read(file); } // compute the gradient and the gradient-flow private void computegflow(BufferedImage image, int[][] gradient, int[][] flow, int THRESHOLD) { int W = image.getWidth(); int H = image.getHeight(); // GrayLevelScale (Luminance) int[][] clum = new int[W][H]; for (int y = 0; y < H; y++) for (int x = 0; x < W; x++) { int rgb=image.getRGB(x,y); int r = (rgb >>16 ) & 0xFF; int g = (rgb >> 8 ) & 0xFF; int b = rgb & 0xFF; clum[x][y] = (int)(0.299*r + 0.587*g + 0.114*b); } // Gradient (sobel) int maxgradient=0; for (int y = 0; y < H-2; y++) for (int x = 0; x < W-2; x++) { int p00 = clum[x+0][y+0]; int p10 = clum[x+1][y+0]; int p20 = clum[x+2][y+0]; int p01 = clum[x+0][y+1]; /*-------------------- */ int p21 = clum[x+2][y+1]; int p02 = clum[x+0][y+2]; int p12 = clum[x+1][y+2]; int p22 = clum[x+2][y+2]; int sx = (p20+2*p21+p22)-(p00+2*p01+p02); int sy = (p02+2*p12+p22)-(p00+2*p10+p10); int snorm = (int)Math.sqrt(sx*sx+sy*sy); gradient[x+1][y+1]=snorm; maxgradient=Math.max(maxgradient, snorm); } // thresholding boolean[][] binarygradient = new boolean[W][H]; for (int y = 0; y < H; y++) for (int x = 0; x < W; x++) if (gradient[x][y] > THRESHOLD*maxgradient/100) { binarygradient[x][y]=true; } else { gradient[x][y]=0; } // distance map to binarized gradient double[][] cdist = new ChamferDistance(ChamferDistance.chamfer5).compute(binarygradient, W,H); for (int y = 0; y < H; y++) for (int x = 0; x < W; x++) flow[x][y]=(int)(5*cdist[x][y]); } public static void main(String[] args) throws Exception { new SnakeCLI().process(args); } }
Au final, ca permet d'executer le code et de récupérer les points via une commande:
java -jar snake.jar imagefile 25 1.0 1.0 1.0 1.0 true 10 8 16 300 > result.txt
bonjour pseudo-code
merci pour votre contribution
j'ai une question concernant le code que vous avez mis dans la duscusion
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 /** * @param f : image normalized in [0,1] * @param w : width of image * @param h : height of image * @param ITER : number of iterations * @param mu : iteration step * @return u[x,y] and v[x,y] arrays */ public static double[][][] gvf(double[][] f, int w, int h, int ITER, double mu) { // create empty arrays double[][] u = new double[w][h]; double[][] v = new double[w][h]; double[][] fx = new double[w][h]; double[][] fy = new double[w][h]; double[][] Lu = new double[w][h]; double[][] Lv = new double[w][h]; // precompute edge-map (gradient) for (int y=1;y<(h-1);y++) { for (int x=1;x<(w-1);x++) { fx[x][y] = (f[x+1][y]-f[x-1][y])/2; fy[x][y] = (f[x][y+1]-f[x][y-1])/2; } } // iterative diffusion for(int loop=0;loop<ITER;loop++) { // compute laplacian of U and V for (int y=1;y<(h-1);y++) { for (int x=1;x<(w-1);x++) { Lu[x][y] = -u[x][y] + 0.25*(u[x-1][y]+u[x+1][y]+u[x][y-1]+u[x][y+1]); Lv[x][y] = -v[x][y] + 0.25*(v[x-1][y]+v[x+1][y]+v[x][y-1]+v[x][y+1]); } } // update U and V for (int y=0;y<h;y++) { for (int x=0;x<w;x++) { double gnorm2 = fx[x][y]*fx[x][y] + fy[x][y]*fy[x][y]; u[x][y] += mu*4*Lu[x][y] - (u[x][y]-fx[x][y])*gnorm2; v[x][y] += mu*4*Lv[x][y] - (v[x][y]-fy[x][y])*gnorm2; } } } // return U and V arrays return new double[][][]{u,v}; }
1. est que je peux remplacer l'énergie g_flow par ce code de gvf
2. si oui , comment normaliser cette énergie
3. quelle sont les étapes pour normaliser (je veux code de java pour normalisé cette energie gvf s il est possible )
merciii
bonsoir
j'est utiliser ce code pour faire un snake avec NURBS pour mon projet de fin d’étude, merci infiniment pour vous.
mais,j'ai pas compris cette partie du code, la dernière boucle de computegflow();
ce que j'ai pas compris c'est dans la 4eme ligne le point d’interrogation et le reste "?255:0"
et la ligne 15 "<<" et ">>"
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 for (int y = 0; y < H; y++) { for (int x = 0; x < W; x++) { int vflow = chanel_flow[x][y]; int vgrad = binarygradient[x][y]?255:0; if (vgrad > 0) { rgb[0] = 0; rgb[1] = vgrad; rgb[2] = 0; } else { rgb[0] = Math.max(0, 255 - vflow); rgb[1] = 0; rgb[2] = 0; } int irgb = (0xFF<<24)+(rgb[0]<<16)+(rgb[1]<<8)+rgb[2]; imgflow.setRGB(x, y, irgb); } }
et merci
C'est de la syntaxe Java, sans plus. Regarde un tutoriel aux sections sur l'opérateur ternaire et les décalages de bits. Par exemple, tout est expliqué dans http://bruce-eckel.developpez.com/li...2/?page=page_5.
merci infiniment dourouc05
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager