Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
FFT.java
1 package ij.plugin;
2 import ij.*;
3 import ij.process.*;
4 import ij.gui.*;
5 import ij.measure.*;
6 import ij.plugin.ContrastEnhancer;
7 import java.awt.*;
8 import java.util.*;
9 
10 
19 public class FFT implements PlugIn, Measurements {
20 
21  private ImagePlus imp;
22  private String arg;
23  private FHT transform;
24  private ImageProcessor filter;
25  private static boolean processStack;
26  private boolean padded;
27  private int originalWidth;
28  private int originalHeight;
29  private int stackSize = 1;
30  private int slice = 1;
31 
32  public void run(String arg) {
33  imp = IJ.getImage();
34  if (arg.equals("redisplay"))
35  {redisplayPowerSpectrum(); return;}
36  ImageProcessor ip = imp.getProcessor();
37  FHT fht = (FHT)imp.getProperty("FHT");
38  stackSize = imp.getStackSize();
39  boolean inverse;
40  if (fht==null && arg.equals("inverse")) {
41  IJ.showMessage("FFT", "Frequency domain image required");
42  return;
43  }
44  if (fht!=null) {
45  inverse = true;
46  imp.killRoi();
47  } else {
48  if (imp.getRoi()!=null)
49  ip = ip.crop();
50  fht = newFHT(ip);
51  inverse = false;
52  }
53  if (inverse)
54  doInverseTransform(fht, ip);
55  else
56  doForewardTransform(fht, ip);
57  IJ.showProgress(1.0);
58  }
59 
60  void doInverseTransform(FHT fht, ImageProcessor ip) {
61  fht = fht.getCopy();
62  doMasking(fht);
63  showStatus("Inverse transform");
64  fht.inverseTransform();
65  if (fht.quadrantSwapNeeded)
66  fht.swapQuadrants();
67  fht.resetMinAndMax();
68  ImageProcessor ip2 = fht;
69  if (fht.originalWidth>0) {
70  fht.setRoi(0, 0, fht.originalWidth, fht.originalHeight);
71  ip2 = fht.crop();
72  }
73  int bitDepth = fht.originalBitDepth>0?fht.originalBitDepth:imp.getBitDepth();
74  switch (bitDepth) {
75  case 8: ip2 = ip2.convertToByte(false); break;
76  case 16: ip2 = ip2.convertToShort(false); break;
77  case 24:
78  showStatus("Setting brightness");
79  if (fht.rgb==null || ip2==null) {
80  IJ.showMessage("FFT", "Unable to set brightness");
81  return;
82  }
83  ColorProcessor rgb = (ColorProcessor)fht.rgb.duplicate();
84  rgb.setBrightness((FloatProcessor)ip2);
85  ip2 = rgb;
86  fht.rgb = null;
87  break;
88  case 32: break;
89  }
90  if (bitDepth!=24 && fht.originalColorModel!=null)
91  ip2.setColorModel(fht.originalColorModel);
92  String title = imp.getTitle();
93  if (title.startsWith("FFT of "))
94  title = title.substring(7, title.length());
95  new ImagePlus("Inverse FFT of "+title, ip2).show();
96  }
97 
98  public void doForewardTransform(FHT fht, ImageProcessor ip) {
99  showStatus("Foreward transform");
100  fht.transform();
101  showStatus("Calculating power spectrum");
102  ImageProcessor ps = fht.getPowerSpectrum();
103  ImagePlus imp2 = new ImagePlus("FFT of "+imp.getTitle(), ps);
104  imp2.show();
105  imp2.setProperty("FHT", fht);
106  }
107 
108  FHT newFHT(ImageProcessor ip) {
109  FHT fht;
110  if (ip instanceof ColorProcessor) {
111  showStatus("Extracting brightness");
112  ImageProcessor ip2 = ((ColorProcessor)ip).getBrightness();
113  fht = new FHT(pad(ip2));
114  fht.rgb = (ColorProcessor)ip.duplicate(); // save so we can later update the brightness
115  } else
116  fht = new FHT(pad(ip));
117  if (padded) {
118  fht.originalWidth = originalWidth;
119  fht.originalHeight = originalHeight;
120  }
121  fht.originalBitDepth = imp.getBitDepth();
122  fht.originalColorModel = ip.getColorModel();
123  return fht;
124  }
125 
126  ImageProcessor pad(ImageProcessor ip) {
127  originalWidth = ip.getWidth();
128  originalHeight = ip.getHeight();
129  int maxN = Math.max(originalWidth, originalHeight);
130  int i = 2;
131  while(i<maxN) i *= 2;
132  if (i==maxN && originalWidth==originalHeight) {
133  padded = false;
134  return ip;
135  }
136  maxN = i;
137  showStatus("Padding to "+ maxN + "x" + maxN);
138  ImageStatistics stats = ImageStatistics.getStatistics(ip, MEAN, null);
139  ImageProcessor ip2 = ip.createProcessor(maxN, maxN);
140  ip2.setValue(stats.mean);
141  ip2.fill();
142  ip2.insert(ip, 0, 0);
143  padded = true;
144  Undo.reset();
145  //new ImagePlus("padded", ip2.duplicate()).show();
146  return ip2;
147  }
148 
149  void showStatus(String msg) {
150  if (stackSize>1)
151  IJ.showStatus("FFT: " + slice+"/"+stackSize);
152  else
153  IJ.showStatus(msg);
154  }
155 
156  void doMasking(FHT ip) {
157  if (stackSize>1)
158  return;
159  float[] fht = (float[])ip.getPixels();
160  ImageProcessor mask = imp.getProcessor();
161  mask = mask.convertToByte(false);
162  ImageStatistics stats = ImageStatistics.getStatistics(mask, MIN_MAX, null);
163  if (stats.histogram[0]==0 && stats.histogram[255]==0)
164  return;
165  boolean passMode = stats.histogram[255]!=0;
166  IJ.showStatus("Masking: "+(passMode?"pass":"filter"));
167  mask = mask.duplicate();
168  if (passMode)
169  changeValues(mask, 0, 254, 0);
170  else
171  changeValues(mask, 1, 255, 255);
172  for (int i=0; i<3; i++)
173  mask.smooth();
174  //imp.updateAndDraw();
175  ip.swapQuadrants(mask);
176  //new ImagePlus("mask", mask.duplicate()).show();
177  byte[] maskPixels = (byte[])mask.getPixels();
178  for (int i=0; i<fht.length; i++) {
179  fht[i] = (float)(fht[i]*(maskPixels[i]&255)/255.0);
180  }
181  //FloatProcessor fht2 = new FloatProcessor(mask.getWidth(),mask.getHeight(),fht,null);
182  //new ImagePlus("fht", fht2.duplicate()).show();
183  }
184 
185  void changeValues(ImageProcessor ip, int v1, int v2, int v3) {
186  byte[] pixels = (byte[])ip.getPixels();
187  int v;
188  //IJ.log(v1+" "+v2+" "+v3+" "+pixels.length);
189  for (int i=0; i<pixels.length; i++) {
190  v = pixels[i]&255;
191  if (v>=v1 && v<=v2)
192  pixels[i] = (byte)v3;
193  }
194  }
195 
196  public void redisplayPowerSpectrum() {
197  FHT fht = (FHT)imp.getProperty("FHT");
198  if (fht==null)
199  {IJ.showMessage("FFT", "Frequency domain image required"); return;}
200  ImageProcessor ps = fht.getPowerSpectrum();
201  imp.setProcessor(null, ps);
202  }
203 
204 }
205