Pour compléter le filtre "Fast Bilatéral", voici une version basique de filtre bilateral. Pour l'instant ca ne fonctionne que sur les images RGB, en travaillant séparément sur les 3 composantes... A améliorer.




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
package millie.plugins.free;
 
import java.awt.image.BufferedImage;
 
import millie.automation.Automatable;
import millie.plugins.PluginInfo;
import millie.plugins.appimage.GenericAppImagePlugin;
import millie.plugins.parameters.DoubleSliderParameter;
import millie.plugins.parameters.IntSliderParameter;
 
/**
 * @author X.Philippeau
 *
 */
@PluginInfo(name="Full Bilateral Filter", category="Restauration", description="Full Bilateral (RGB)")
public class FullBilateralPlugin extends GenericAppImagePlugin implements Automatable {
 
	public FullBilateralPlugin() {
		setRefreshable(false);
		setCacheable(true);
		setLongProcessing(true);
 
		addParameter(new IntSliderParameter("size", "Size", 1, 10, 3));
		addParameter(new DoubleSliderParameter("factor", "Smooth/Strength", 1, 10, 0.1, 5));
		addParameter(new IntSliderParameter("iter", "Iteration(s)", 1,20,1));
	}
 
	@Override
	public BufferedImage filter() throws Exception {
 
		int radius = getIntValue("size");
		int iter = getIntValue("iter");
		double factor = getDoubleValue("factor");
 
		// weight function for similarity distance 
		double[][] w_similarity = new double[256][256];
		for(int i=0;i<256;i++) {
			double x = (double)i/255;
			for(int j=0;j<256;j++) {
				double y = (double)j/255;
 
				double lx = Math.pow(x,0.33);
				double ly = Math.pow(y,0.33);
				double d = Math.abs(lx-ly)*Math.pow(2, factor); 
				w_similarity[i][j] = Math.exp(-d*d);
			}
		}
 
		// weight function for spatial distance 
		double[][] w_spatial = new double[2*radius+1][2*radius+1];
		double w_spatial_sum = 0;
		double sigma2 = Math.pow(radius/2.5, 2);
		for(int i=0;i<2*radius+1;i++) {
			for(int j=0;j<2*radius+1;j++) {
				double x = i-radius;
				double y = j-radius;
				w_spatial[i][j] = Math.exp(-(x*x+y*y)/(2*sigma2));
				w_spatial_sum += w_spatial[i][j];
			}
		}
		for(int i=0;i<2*radius+1;i++)
			for(int j=0;j<2*radius+1;j++)
				w_spatial[i][j]/=w_spatial_sum;
 
		// initial image
		BufferedImage initialImage = getInputImage();
		int W=initialImage.getWidth(), H=initialImage.getHeight();
 
		// work image
		BufferedImage input = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
		for(int y=0;y<H;y++) for(int x=0;x<W;x++) input.setRGB(x, y, initialImage.getRGB(x, y));
		BufferedImage output = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
 
		// iteration loop
		for(int loop=0;loop<iter;loop++) {
			if (loop>0) {BufferedImage temp=input;input=output;output=temp;}
 
			// for each pixel in image
			for(int y=0;y<H;y++) {
				for(int x=0;x<W;x++) {
 
					// get value in input image
					int r = input.getRaster().getSample(x, y, 0);
					int g = input.getRaster().getSample(x, y, 1);
					int b = input.getRaster().getSample(x, y, 2);
 
					double newr=0, newg=0, newb=0;
					double sumrw=0, sumgw=0, sumbw=0;
 
					// local convolution
					for(int dy=-radius;dy<=radius;dy++) {
						for(int dx=-radius;dx<=radius;dx++) {
							int xk = x+dx, yk=y+dy;
							if (xk<0 || xk>=W) continue;
							if (yk<0 || yk>=H) continue;
 
							// rgb value in input image 
							int rk = input.getRaster().getSample(xk, yk, 0);
							int gk = input.getRaster().getSample(xk, yk, 1);
							int bk = input.getRaster().getSample(xk, yk, 2);
 
							// rgb value in initial image
							int r0k = initialImage.getRaster().getSample(xk, yk, 0);
							int g0k = initialImage.getRaster().getSample(xk, yk, 1);
							int b0k = initialImage.getRaster().getSample(xk, yk, 2);
 
							// weight for each component spatial*similarity
							double rw = w_spatial[dx+radius][dy+radius]*w_similarity[r][rk];
							double gw = w_spatial[dx+radius][dy+radius]*w_similarity[g][gk];
							double bw = w_spatial[dx+radius][dy+radius]*w_similarity[b][bk];
 
							// weighted sum for each component
							newr += rw*r0k; sumrw+=rw;
							newg += gw*g0k; sumgw+=gw;
							newb += bw*b0k; sumbw+=bw;
						}
					}
 
					// set value in ouput image
					output.getRaster().setSample(x, y, 0, (int)(0.5+newr/sumrw));
					output.getRaster().setSample(x, y, 1, (int)(0.5+newg/sumgw));
					output.getRaster().setSample(x, y, 2, (int)(0.5+newb/sumbw));
				}
			}
		}
 
		return output;
	}
 
}