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;
}
} |
Partager