Voici la version de base de l'opérateur de Nagao
Classe Générique AreaOperator non multithreadé
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
128
129
130
131
132
133
134
135
136
137 /** * */ package millie.operator.commons.area; import millie.image.Image; import millie.operator.commons.ImageOperator; import millie.operator.extender.BorderExtender; /** * Cette classe permet de définir des opérateurs travaillant sur des rectangles * autour du pixel d'origine pour calculer la couleur de destination * * Il est nécessaire de supposer que l'image de destination et l'image d'origine * doivent avoir le même nombre de composantes avec ce type d'opérateur. * * @version 1.00 */ public abstract class AreaOperator implements ImageOperator { private BorderExtender extender = null; private int toppadding; private int leftpadding; private int rightpadding; private int bottompadding; public AreaOperator(int toppadding, int leftpadding, int rightpadding, int bottompadding, BorderExtender extender) { this.extender = extender; this.toppadding = toppadding; this.leftpadding = leftpadding; this.rightpadding = rightpadding; this.bottompadding = bottompadding; } /** * applique l'opérateur * * @param out l'image de sortie * @param in l'image d'entrée * * @throw IllegalArgumentException si le nombre de composantes * de out et de in ne sont pas égales * * A noter que l'image de sortie sera de la taille : <pre> largeur de in - (leftpadding + rightpadding) hauteur de in - (toppadding + bottompadding) </pre> * * @see millie.operator.commons.ImageOperator#compute(millie.image.Image, * millie.image.Image) */ public void compute(Image out, Image in) throws Exception { if(extender==null) { if (out.getNumComponents() != in.getNumComponents()) throw new IllegalArgumentException("AreaOperator::compute"); int leftpadding = op.getLeftPadding(); int rightpadding = op.getRightPadding(); int toppadding = op.getTopPadding(); int bottompadding = op.getBottomPadding(); int hauteur = in.getHeight(); int largeur = in.getWidth(); out.resize(largeur - (rightpadding + leftpadding), hauteur - (toppadding + bottompadding)); for (int canal = 0; canal < in.getNumComponents(); canal++) for (int j = toppadding; j < hauteur - bottompadding; j++) { for (int i = leftpadding; i < largeur - rightpadding; i++) { out.setPixel(i - leftpadding, j - toppadding, canal, op .computeLocalArea(in, i, j, canal)); } } } else compute(out, in, extender); } public void compute(Image out, Image in, BorderExtender e) throws Exception { Image tempo = new Image(in.getNumComponents()); extender.extend(tempo, in, getTopPadding(), getLeftPadding(), getRightPadding(), getBottomPadding()); op.compute(out, in, this); } /** * @return retourne le padding supérieur */ public int getTopPadding() { return toppadding; } /** * @return retourne le padding inférieur */ public int getBottomPadding() { return bottompadding; } /** * @return retourne le padding à gauche */ public int getLeftPadding() { return leftpadding; } /** * @return retourne le padding à droite */ public int getRightPadding() { return rightpadding; } /** * calcul la couleur de destination * * @param in * l'image où calculer la couleur de destination * @param x * la position horizontale * @param y * la position verticale * @param canal * le canal de l'image */ public abstract double computeLocalArea(Image in, int x, int y, int canal); }
L'opérateur proprement dit
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
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 /** * */ package millie.operator; import java.util.ArrayList; import java.util.List; import millie.image.Image; import millie.image.Kernel; import millie.operator.commons.area.AreaOperator; import millie.operator.extender.BorderExtender; import millie.util.MillieUtil; /** * @author millie * */ public class NagaoOperator extends AreaOperator { private Kernel[] kernels; private double computeAverage(List<Double> vect) { return MillieUtil.getMean(vect); } private double computeVariance(List<Double> vect, double moyenne) { double variance = 0; for(Double d : vect) variance += MillieUtil.square(d - moyenne); return variance; } public NagaoOperator() { this(null); } public NagaoOperator(BorderExtender extender) { super(2, 2, 2, 2, extender); double a [] = { 1,1,0, 1,1,1, 0,1,1 }; Kernel ka = new Kernel(3,3,2,2,a); double e [] = { 1,1,1, 1,1,1, 0,1,0 }; Kernel ke = new Kernel(3,3,1,2,e); double b [] = { 0,1,1, 1,1,1, 1,1,0 }; Kernel kb = new Kernel(3,3,0,2,b); double h [] = { 1,1,0, 1,1,1, 1,1,0 }; Kernel kh = new Kernel(3,3,2,1,h); double f [] = { 0,1,1, 1,1,1, 0,1,1 }; Kernel kf = new Kernel(3,3,0,1,f); double d[] = { 0,1,1, 1,1,1, 1,1,0 }; Kernel kd = new Kernel(3,3,2,0,d); double g[] = { 0,1,0, 1,1,1, 1,1,1 }; Kernel kg = new Kernel(3,3,1,0,g); double c[] = { 1,1,0, 1,1,1, 0,1,1 }; Kernel kc = new Kernel(3,3,0,0,c); kernels = new Kernel[8]; kernels[0] = ka; kernels[1] = ke; kernels[2] = kb; kernels[3] = kh; kernels[4] = kf; kernels[5] = kd; kernels[6] = kg; kernels[7] = kc; } class CoupleVarianceAverage { double variance; double average; } private double getAverageOfMinimumVariance(List<CoupleVarianceAverage> vect) { if(vect.size() == 0) throw new IllegalArgumentException("getAverageOfMinimumVariance size null"); CoupleVarianceAverage min = null; for(CoupleVarianceAverage c : vect) { if(min==null) min =c; else { if(min.variance > c.variance) min = c; } } return min.average; } /* (non-Javadoc) * @see millie.operator.commons.area.AreaOperator#computeLocalArea(millie.image.Image, int, int, int) */ @Override public double computeLocalArea(Image in, int i, int j, int canal) { /*stocke toutes les valeurs de l'image là ou le noyau vaut 1 à un position donnée*/ List<Double> allKernelValue = new ArrayList<Double>(); /*stocke toutes les variances et moyenne pour tous les noyaux à une position donnée*/ List<CoupleVarianceAverage> allVarianceAverage = new ArrayList<CoupleVarianceAverage>(); for(int vectKerneli = 0; vectKerneli < kernels.length; vectKerneli++) { allKernelValue.clear(); Kernel currentKernel = kernels[vectKerneli]; for(int kj =0; kj< currentKernel.getHeight(); kj++) for(int ki = 0; ki< currentKernel.getWidth(); ki++) { /*si le masque vaut 1 à cette position, on enregistre le pixel*/ if(currentKernel.getElement(ki, kj) == 1) allKernelValue.add( in.getPixel(i-currentKernel.getXOrigin() + ki, j-currentKernel.getYOrigin() + kj, canal)); } /*on enregistre la variance et la moyenne pour tous ces pixels*/ CoupleVarianceAverage couple = new CoupleVarianceAverage(); couple.average = computeAverage(allKernelValue); couple.variance = computeVariance(allKernelValue, couple.average); allVarianceAverage.add(couple); } /*on détermine le noyau pour lequel la variance est minimal * et on retourne le pixel correspondant à la moyenne du noyau */ return getAverageOfMinimumVariance(allVarianceAverage); } }
PRomu@ld : sources
Partager