Commit ed19c6c4 authored by Andrey Filippov's avatar Andrey Filippov

test pattern generator

parent ec11a1dd
import java.util.Arrays;
import java.util.Random;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.GenericDialog;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
/*
**
** WavePatternGenerator.java
**
** Copyright (C) 2014 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** WavePatternGenerator.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
public class WavePatternGenerator {
String DEFAULT_DIRECTORY=null;
// / GenericDialog gd=new GenericDialog("Select images "+startIndex+"..."+(endIndex-1));
public boolean selectAndGenerate(){
GenericDialog gd=new GenericDialog("Select wave pattern parameters");
boolean generateCirc=false;
boolean generateFFT=false;
int width=4096;
int height=4096;
double period=10.0;
double x0=width/2;
double y0=height/2;
boolean binary=false;
int fft_size= 4096;
boolean useSelectedImage=false;
double fxc=0.15; // center frequency X (0..0.5)
double fyc=0.05; // center frequency Y (0..0.5)
double sigma_long=0.001; // coeff for x^2, relative to full size
double sigma_lat= 0.001; //
gd.addCheckbox("Halftone",!binary);
gd.addMessage("=== Circular waves generation ===");
gd.addCheckbox("Generate circular wave pattern",generateCirc);
gd.addNumericField("Image width", width, 0, 4, "pixels");
gd.addNumericField("Image height", height, 0, 4, "pixels");
gd.addNumericField("Wave period", period, 2, 6, "pixels");
gd.addNumericField("Wave center X", x0, 2, 10, "pixels");
gd.addNumericField("Wave center Y", y0, 2, 10, "pixels");
gd.addMessage("=== FFT filter ===");
gd.addCheckbox("Generate FFT-fileterd wave pattern",generateFFT);
gd.addCheckbox("Use selected image (otherwise use random data)",useSelectedImage);
gd.addNumericField("FFT size", fft_size, 0, 4, "pixels");
gd.addNumericField("Filter center X (frequency domain)", fxc, 5, 7, "fraction");
gd.addNumericField("Filter center Y (frequency domain)", fyc, 5, 7, "fraction");
gd.addNumericField("Filter half-width longitudinal", sigma_long, 5, 7, "fraction");
gd.addNumericField("Filter half-width lateral", sigma_lat, 5, 7, "fraction");
// WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
binary= !gd.getNextBoolean();
generateCirc= gd.getNextBoolean();
width= (int) gd.getNextNumber();
height= (int) gd.getNextNumber();
period= gd.getNextNumber();
x0= gd.getNextNumber();
y0= gd.getNextNumber();
generateFFT= gd.getNextBoolean();
fft_size= (int) gd.getNextNumber();
fxc= gd.getNextNumber();
fyc= gd.getNextNumber();
sigma_long= gd.getNextNumber();
sigma_lat= gd.getNextNumber();
if (generateCirc) {
circularPatternGenerator(
width,
height,
period,
x0,
y0,
binary);
}
if (generateFFT) {
FHTFilter (
fft_size,
useSelectedImage?WindowManager.getCurrentImage():null, // input image or null (will use random)
fxc, // center frequency X (0..0.5)
fyc, // center frequency Y (0..0.5)
sigma_long, // coeff for x^2, relative to full size
sigma_lat, //
binary);
}
return true;
}
public ImagePlus FHTFilter (
int size,
ImagePlus imp_in, // input image or null (will use random)
double fxc, // center frequency X (0..0.5)
double fyc, // center frequency Y (0..0.5)
double sigma_long, // coeff for x^2, relative to full size
double sigma_lat, //
boolean binary
){
// Random random=new Random();
// double rnd=random.nextDouble();
double kSigma=5.0;
double vLen=Math.sqrt(fxc*fxc+fyc*fyc);
double [] vLong={fxc/vLen, fyc/vLen};
double [] vLat= {-fyc/vLen, fxc/vLen};
double [] data=new double[size*size];
if (imp_in!=null){
int iWidth=imp_in.getWidth();
int iHeight=imp_in.getHeight();
int dy=iHeight/2-size/2;
int dx=iWidth/2-size/2;
float [] fpixels= (float[]) imp_in.getProcessor().getPixels();
for (int y=0;y<size;y++){
int y_in=y+dy;
if ((y_in<0) || (y_in>=iHeight)) y_in=-1;
for (int x=0;x<size;x++){
if (y_in<0) data[y*size+x]=0.0;
else {
int x_in=x+dx;
if ((x_in<0) || (x_in>=iWidth)) data[y*size+x]=0.0;
else {
data[y*size+x]=fpixels[y_in*iWidth+x_in];
}
}
}
}
} else {
Random random=new Random();
for (int i=0;i<data.length;i++) data[i]=random.nextDouble();
}
// generate frequency mask
double [] mask=new double[size*size];
Arrays.fill(mask,0.0);
int ifxc=(int) Math.round(fxc*size);
int ifyc=(int) Math.round(fyc*size);
int iRangeX= (int) Math.round((sigma_long*Math.abs(vLong[0]) + sigma_lat*Math.abs(vLat[0]))* size*kSigma);
int iRangeY= (int) Math.round((sigma_long*Math.abs(vLong[1]) + sigma_lat*Math.abs(vLat[1]))* size*kSigma);
double kLong= -0.5/(sigma_long*sigma_long*size*size);
double kLat= -0.5/(sigma_lat* sigma_lat* size*size);
for (int y=ifyc-iRangeY;y<ifyc+iRangeY;y++){
int iy=(y+size)%size;
int base=size*iy;
for (int x=ifxc-iRangeX;x<ifxc+iRangeX;x++){
int ix=(x+size)%size;
double cLong=(x-ifxc)*vLong[0]+(y-ifyc)*vLong[1];
double cLat= (x-ifxc)*vLat[0]+ (y-ifyc)*vLat[1];
mask[base+ix]=Math.exp(kLong*cLong*cLong+kLat*cLat*cLat);
}
}
(new showDoubleFloatArrays()).showArrays(data, "input data");
(new showDoubleFloatArrays()).showArrays(mask, "mask");
DoubleFHT fht =new DoubleFHT();
fht.swapQuadrants(data);
fht.transform( data);
(new showDoubleFloatArrays()).showArrays(data, "FHT data");
for (int i=0;i<data.length;i++) data[i]*=mask[i];
(new showDoubleFloatArrays()).showArrays(data, "masked FHT data");
fht.inverseTransform(data);
fht.swapQuadrants (data);
// (new showDoubleFloatArrays()).showArrays(data, "restored data");
float [] pixels = new float [data.length];
if (binary) for (int i=0;i<data.length;i++) pixels[i] = (data[i]>0)?1.0f:0.0f;
else for (int i=0;i<data.length;i++) pixels[i] = (float) data[i];
ImageProcessor ip_wave = new FloatProcessor(size,size);
ip_wave.setPixels(pixels);
ip_wave.resetMinAndMax();
ImagePlus imp_circle= new ImagePlus("wave_fxc"+fxc+"_fyc"+fyc+"_sigma_long"+sigma_long+"_sigma_lat"+sigma_lat,ip_wave);
imp_circle.show();
return imp_circle;
}
public ImagePlus circularPatternGenerator(
int width,
int height,
double period,
double centerX,
double centerY,
boolean binary
){
ImageProcessor ip_cirWave = new FloatProcessor(width,height);
float [] pixels = new float [width*height];
double l=period/Math.PI;
for (int y=0;y<height;y++){
int base=y*width;
for (int x=0;x<width;x++){
double dx=x-centerX;
double dy=y-centerY;
double r=Math.sqrt(dx*dx+dy*dy);
float d=(float) Math.sin(r/l);
pixels[base+x]=binary?((d>0)?1.0f:0.0f):d;
}
}
ip_cirWave.setPixels(pixels);
ip_cirWave.resetMinAndMax();
ImagePlus imp_circle= new ImagePlus("circularWaves_period"+period+"_xc"+centerX+"_yc"+centerY,ip_cirWave);
imp_circle.show();
return imp_circle;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment