|
4 | 4 | import ij.process.*; |
5 | 5 | import ij.gui.GenericDialog; |
6 | 6 | import ij.util.ThreadUtil; |
7 | | -import ij.plugin.RGBStackMerge; |
8 | | -import ij.gui.*; |
9 | 7 | import java.util.concurrent.atomic.AtomicInteger; |
10 | 8 |
|
11 | 9 | /* |
|
15 | 13 | public class Filters3D implements PlugIn { |
16 | 14 | public final static int MEAN=10, MEDIAN=11, MIN=12, MAX=13, VAR=14, MAXLOCAL=15; |
17 | 15 | private static float xradius = 2, yradius = 2, zradius = 2; |
| 16 | + private static boolean doAllFrms=true; |
| 17 | + private static boolean doAllChs=true; |
18 | 18 |
|
19 | 19 | public void run(String arg) { |
20 | 20 | String name = null; |
@@ -45,103 +45,124 @@ public void run(String arg) { |
45 | 45 | return; |
46 | 46 | imp.startTiming(); |
47 | 47 | run(imp, filter, xradius, yradius, zradius); |
48 | | - IJ.showTime(imp, imp.getStartTime(), "", imp.getStackSize()); |
| 48 | + int nProcessedSlices=imp.getStackSize(); |
| 49 | + if(!doAllChs)nProcessedSlices/=imp.getNChannels(); |
| 50 | + if(!doAllFrms)nProcessedSlices/=imp.getNFrames(); |
| 51 | + IJ.showTime(imp, imp.getStartTime(), "", nProcessedSlices); |
49 | 52 | } |
50 | 53 |
|
51 | 54 | private boolean showDialog(String name) { |
| 55 | + ImagePlus imp = IJ.getImage(); |
52 | 56 | GenericDialog gd = new GenericDialog(name); |
53 | 57 | gd.addNumericField("X radius:", xradius, 1); |
54 | 58 | gd.addNumericField("Y radius:", yradius, 1); |
55 | 59 | gd.addNumericField("Z radius:", zradius, 1); |
| 60 | + if(imp.getNChannels()>1)gd.addCheckbox("SingleChannel (current channel only)", !doAllChs); |
| 61 | + if(imp.getNFrames()>1)gd.addCheckbox("SingleFrame (current frame only)", !doAllFrms); |
56 | 62 | gd.showDialog(); |
57 | 63 | if (gd.wasCanceled()) { |
58 | 64 | return false; |
59 | 65 | } |
60 | 66 | xradius = (float) gd.getNextNumber(); |
61 | 67 | yradius = (float) gd.getNextNumber(); |
62 | 68 | zradius = (float) gd.getNextNumber(); |
| 69 | + if(imp.getNChannels()>1)doAllChs=!gd.getNextBoolean(); |
| 70 | + if(imp.getNFrames()>1)doAllFrms=!gd.getNextBoolean(); |
63 | 71 | return true; |
64 | 72 | } |
65 | 73 |
|
66 | 74 | private void run(ImagePlus imp, int filter, float radX, float radY, float radZ) { |
67 | | - if (imp.isHyperStack()) { |
68 | | - filterHyperstack(imp, filter, radX, radY, radZ); |
69 | | - return; |
70 | | - } |
71 | | - ImageStack res = filter(imp.getStack(), filter, radX, radY, radZ); |
| 75 | + int cmax=imp.getC(), cmin=cmax-1, tmax=imp.getT(), tmin=tmax-1, nZSlices=imp.getNSlices(); |
| 76 | + if(doAllChs) { cmin=0; cmax=imp.getNChannels(); } |
| 77 | + if(doAllFrms) { tmin=0; tmax=imp.getNFrames(); } |
| 78 | + if(imp.getStackSize()==imp.getNFrames()) nZSlices=imp.getNFrames(); |
| 79 | + ImageStack res = filter(imp.getStack(), filter, radX, radY, radZ, imp.getNChannels(), nZSlices, cmin, cmax, tmin, tmax); |
72 | 80 | imp.setStack(res); |
73 | 81 | } |
74 | | - |
| 82 | + |
75 | 83 | public static ImageStack filter(ImageStack stackorig, int filter, float vx, float vy, float vz) { |
| 84 | + return filter(stackorig, filter, vx, vy, vz, 1, stackorig.size(), 0, 1, 0, 1); |
| 85 | + } |
76 | 86 |
|
77 | | - if (stackorig.getBitDepth()==24) |
78 | | - return filterRGB(stackorig, filter, vx, vy, vz); |
| 87 | + /** |
| 88 | + * Original functionality was for a single stack, so if imp is not provided, then |
| 89 | + * assume a non-hyperstack. |
| 90 | + * |
| 91 | + * @param imp Required if a hyperstack, otherwise null is ok |
| 92 | + * @param stack ImageStack |
| 93 | + * @param filter |
| 94 | + * @param vx |
| 95 | + * @param vy |
| 96 | + * @param vz |
| 97 | + * @return |
| 98 | + */ |
| 99 | + public static ImageStack filter(final ImageStack stack, final int filter, final float vx, final float vy, final float vz, |
| 100 | + final int nChs, int numberOfZSlices, int cmin, int cmax, int tmin, int tmax) { |
| 101 | + |
| 102 | + if (stack.getBitDepth()==24) |
| 103 | + return filterRGB(stack, filter, vx, vy, vz, numberOfZSlices, tmin, tmax); |
79 | 104 |
|
80 | 105 | // get stack info |
81 | | - final ImageStack stack = stackorig; |
82 | | - final float voisx = vx; |
83 | | - final float voisy = vy; |
84 | | - final float voisz = vz; |
85 | 106 | final int width= stack.getWidth(); |
86 | 107 | final int height= stack.getHeight(); |
87 | 108 | final int depth= stack.size(); |
| 109 | + if(numberOfZSlices>depth) numberOfZSlices=depth; |
| 110 | + final int nZSlices=numberOfZSlices; |
| 111 | + if(cmin<0) cmin=0; |
| 112 | + if(tmin<0) tmin=0; |
| 113 | + if(cmax<nChs) cmax=nChs; |
| 114 | + if(tmax>(depth/nChs/nZSlices)) tmax=depth/nChs/nZSlices; |
88 | 115 | ImageStack res = null; |
89 | 116 |
|
90 | 117 | if ((filter==MEAN) || (filter==MEDIAN) || (filter==MIN) || (filter==MAX) || (filter==VAR)) { |
91 | 118 | if (filter==VAR) |
92 | 119 | res = ImageStack.create(width, height, depth, 32); |
93 | 120 | else |
94 | | - res = ImageStack.create(width, height, depth, stackorig.getBitDepth()); |
| 121 | + res = ImageStack.create(width, height, depth, stack.getBitDepth()); |
95 | 122 | IJ.showStatus("3D filtering..."); |
96 | 123 | // PARALLEL |
97 | 124 | final ImageStack out = res; |
98 | 125 | final AtomicInteger ai = new AtomicInteger(0); |
99 | 126 | final int n_cpus = Prefs.getThreads(); |
100 | 127 |
|
101 | | - final int f = filter; |
102 | 128 | final int dec = (int) Math.ceil((double) stack.size() / (double) n_cpus); |
103 | | - Thread[] threads = ThreadUtil.createThreadArray(n_cpus); |
104 | | - for (int ithread = 0; ithread < threads.length; ithread++) { |
105 | | - threads[ithread] = new Thread() { |
106 | | - public void run() { |
107 | | - StackProcessor processor = new StackProcessor(stack); |
108 | | - for (int k = ai.getAndIncrement(); k < n_cpus; k = ai.getAndIncrement()) { |
109 | | - processor.filter3D(out, voisx, voisy, voisz, dec * k, dec * (k + 1), f); |
| 129 | + for(int fr=0; fr< (depth/nZSlices/nChs); fr++) { |
| 130 | + for(int ch=0; ch<nChs; ch++) { |
| 131 | + if( fr>=tmin && fr<tmax && ch>=cmin && ch<cmax) { |
| 132 | + final int chf=ch; |
| 133 | + final int frf=fr; |
| 134 | + ai.set(0); |
| 135 | + Thread[] threads = ThreadUtil.createThreadArray(n_cpus); |
| 136 | + for (int ithread = 0; ithread < threads.length; ithread++) { |
| 137 | + threads[ithread] = new Thread() { |
| 138 | + public void run() { |
| 139 | + StackProcessor processor = new StackProcessor(stack); |
| 140 | + for (int k = ai.getAndIncrement(); k < n_cpus; k = ai.getAndIncrement()) { |
| 141 | + processor.filter3D(out, nChs, nZSlices, vx, vy, vz, chf, chf+1, dec * k, dec * (k + 1), frf, frf+1, filter); |
| 142 | + } |
| 143 | + } |
| 144 | + }; |
| 145 | + } |
| 146 | + ThreadUtil.startAndJoin(threads); |
| 147 | + }else { |
| 148 | + for(int sl=0;sl<nZSlices;sl++) { |
| 149 | + int index=1+ch+(nChs*sl)+(nChs*nZSlices*fr); |
| 150 | + out.setProcessor(stack.getProcessor(index),index); |
| 151 | + out.setSliceLabel(stack.getSliceLabel(index), index); |
110 | 152 | } |
111 | 153 | } |
112 | | - }; |
| 154 | + } |
113 | 155 | } |
114 | | - ThreadUtil.startAndJoin(threads); |
| 156 | + |
115 | 157 | } |
116 | 158 | return res; |
117 | 159 | } |
118 | | - |
119 | | - private static void filterHyperstack(ImagePlus imp, int filter, float vx, float vy, float vz) { |
120 | | - if (imp.getNDimensions()>4) { |
121 | | - IJ.error("5D hyperstacks are currently not supported"); |
122 | | - return; |
123 | | - } |
124 | | - if (imp.getNChannels()==1) { |
125 | | - ImageStack stack = filter(imp.getStack(), filter, vx, vy, vz); |
126 | | - imp.setStack(stack); |
127 | | - return; |
128 | | - } |
129 | | - ImagePlus[] channels = ChannelSplitter.split(imp); |
130 | | - int n = channels.length; |
131 | | - for (int i=0; i<n; i++) { |
132 | | - ImageStack stack = filter(channels[i].getStack(), filter, vx, vy, vz); |
133 | | - channels[i].setStack(stack); |
134 | | - } |
135 | | - ImagePlus imp2 = RGBStackMerge.mergeChannels(channels, false); |
136 | | - imp.setImage(imp2); |
137 | | - imp.setC(1); |
138 | | - } |
139 | 160 |
|
140 | | - private static ImageStack filterRGB(ImageStack rgb_in, int filter, float vx, float vy, float vz) { |
| 161 | + private static ImageStack filterRGB(ImageStack rgb_in, int filter, float vx, float vy, float vz, int nZSlices, int tmin, int tmax) { |
141 | 162 | ImageStack[] channels = ChannelSplitter.splitRGB(rgb_in, false); |
142 | | - ImageStack red = filter(channels[0], filter, vx, vy, vz); |
143 | | - ImageStack green = filter(channels[1], filter, vx, vy, vz); |
144 | | - ImageStack blue = filter(channels[2], filter, vx, vy, vz); |
| 163 | + ImageStack red = filter(channels[0], filter, vx, vy, vz, 1, nZSlices, 0, 1, tmin, tmax); |
| 164 | + ImageStack green = filter(channels[1], filter, vx, vy, vz, 1, nZSlices, 0, 1, tmin, tmax); |
| 165 | + ImageStack blue = filter(channels[2], filter, vx, vy, vz, 1, nZSlices, 0, 1, tmin, tmax); |
145 | 166 | return RGBStackMerge.mergeStacks(red, green, blue, false); |
146 | 167 | } |
147 | 168 |
|
|
0 commit comments