Skip to content

Commit 8017878

Browse files
add support for Highest SetupId wins fusion strategy @tpietzsch
I made a new class with minimal changes to not affect performance, what do you think?
1 parent 0786cab commit 8017878

File tree

4 files changed

+241
-6
lines changed

4 files changed

+241
-6
lines changed

src/main/java/net/preibisch/mvrecon/fiji/plugin/fusion/FusionGUI.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ public class FusionGUI implements FusionExportInterface
8080
public static String[] interpolationTypes = new String[]{ "Nearest Neighbor", "Linear Interpolation" };
8181
public static int defaultInterpolation = 1;
8282

83-
public enum FusionType { AVG, AVG_BLEND, AVG_CONTENT, AVG_BLEND_CONTENT, MAX, FIRST }
84-
public static String[] fusionTypes = new String[]{ "Avg", "Avg, Blending", "Avg, Content Based", "Avg, Blending & Content Based", "Max intensity", "First Tile Wins (lowest ViewSetupId)" };
83+
public enum FusionType { AVG, AVG_BLEND, AVG_CONTENT, AVG_BLEND_CONTENT, MAX, FIRST_LOW, FIRST_HIGH }
84+
public static String[] fusionTypes = new String[]{ "Avg", "Avg, Blending", "Avg, Content Based", "Avg, Blending & Content Based", "Max intensity", "First Tile Wins (lowest ViewSetupId)", "First Tile Wins (highest ViewSetupId)" };
8585
public static int defaultFusionType = 1;
8686

8787
public static String[] pixelTypes1 = new String[]{ "32-bit floating point", "16-bit unsigned integer", "8-bit unsigned integer" };

src/main/java/net/preibisch/mvrecon/fiji/plugin/interestpointdetection/DifferenceOfGUI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ protected ImagePlus getGroupedImagePlusForInteractive( final String dialogHeader
694694
registrationsAdjusted,
695695
viewDescriptions,
696696
group.getViews(),
697-
FusionType.FIRST,
697+
FusionType.FIRST_LOW,
698698
DisplayFusedImagesPopup.defaultInterpolation,
699699
bbDS,
700700
null );

src/main/java/net/preibisch/mvrecon/process/fusion/blk/BlkAffineFusion.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ public static < T extends RealType< T > & NativeType< T > > RandomAccessibleInte
151151
weights.add( Blending.create( inputImg, border, blending, transform ) );
152152
break;
153153
case MAX:
154-
case FIRST:
154+
case FIRST_LOW:
155+
masks.add( Masking.create( inputImg, border, transform ) );
156+
break;
157+
case FIRST_HIGH:
155158
masks.add( Masking.create( inputImg, border, transform ) );
156159
break;
157160
case AVG_CONTENT:
@@ -172,9 +175,12 @@ public static < T extends RealType< T > & NativeType< T > > RandomAccessibleInte
172175
case MAX:
173176
floatBlocks = MaxIntensity.of( images, masks, overlap );
174177
break;
175-
case FIRST:
178+
case FIRST_LOW:
176179
floatBlocks = FirstWins.of( images, masks, overlap );
177180
break;
181+
case FIRST_HIGH:
182+
floatBlocks = FirstWinsHighest.of( images, masks, overlap );
183+
break;
178184
case AVG_CONTENT:
179185
case AVG_BLEND_CONTENT:
180186
default:
@@ -284,7 +290,8 @@ private static boolean supports(
284290
switch ( fusionType )
285291
{
286292
case AVG_BLEND:
287-
case FIRST:
293+
case FIRST_LOW:
294+
case FIRST_HIGH:
288295
case MAX:
289296
case AVG:
290297
break;
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*-
2+
* #%L
3+
* Software for the reconstruction of multi-view microscopic acquisitions
4+
* like Selective Plane Illumination Microscopy (SPIM) Data.
5+
* %%
6+
* Copyright (C) 2012 - 2025 Multiview Reconstruction developers.
7+
* %%
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as
10+
* published by the Free Software Foundation, either version 2 of the
11+
* License, or (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public
19+
* License along with this program. If not, see
20+
* <http://www.gnu.org/licenses/gpl-2.0.html>.
21+
* #L%
22+
*/
23+
package net.preibisch.mvrecon.process.fusion.blk;
24+
25+
import static net.imglib2.type.PrimitiveType.BYTE;
26+
import static net.imglib2.type.PrimitiveType.FLOAT;
27+
import static net.imglib2.util.Util.safeInt;
28+
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
31+
import java.util.List;
32+
33+
import net.imglib2.Interval;
34+
import net.imglib2.algorithm.blocks.AbstractBlockSupplier;
35+
import net.imglib2.algorithm.blocks.BlockSupplier;
36+
import net.imglib2.blocks.BlockInterval;
37+
import net.imglib2.blocks.TempArray;
38+
import net.imglib2.type.numeric.integer.UnsignedByteType;
39+
import net.imglib2.type.numeric.real.FloatType;
40+
import net.imglib2.util.Cast;
41+
import net.imglib2.util.Intervals;
42+
43+
class FirstWinsHighest
44+
{
45+
public static BlockSupplier< FloatType > of(
46+
final List< BlockSupplier< FloatType > > images,
47+
final List< BlockSupplier< UnsignedByteType > > masks,
48+
final Overlap overlap )
49+
{
50+
return new FirstWinsBlockSupplier( images, masks, overlap );
51+
}
52+
53+
private static class FirstWinsBlockSupplier extends AbstractBlockSupplier< FloatType >
54+
{
55+
private final int numDimensions;
56+
57+
private final List< BlockSupplier< FloatType > > images;
58+
59+
private final List< BlockSupplier< UnsignedByteType > > masks;
60+
61+
private final Overlap overlap;
62+
63+
private final TempArray< byte[] > tempArrayM;
64+
65+
private final TempArray< byte[] > tempArrayAccM;
66+
67+
private final TempArray< float[] > tempArrayI;
68+
69+
FirstWinsBlockSupplier(
70+
final List< BlockSupplier< FloatType > > images,
71+
final List< BlockSupplier< UnsignedByteType > > masks,
72+
final Overlap overlap )
73+
{
74+
this.numDimensions = images.get( 0 ).numDimensions();
75+
this.images = images;
76+
this.masks = masks;
77+
this.overlap = overlap;
78+
tempArrayM = TempArray.forPrimitiveType( BYTE );
79+
tempArrayAccM = TempArray.forPrimitiveType( BYTE );
80+
tempArrayI = TempArray.forPrimitiveType( FLOAT );
81+
}
82+
83+
private FirstWinsBlockSupplier( final FirstWinsBlockSupplier s )
84+
{
85+
numDimensions = s.numDimensions;
86+
images = new ArrayList<>( s.images.size() );
87+
masks = new ArrayList<>( s.masks.size() );
88+
s.images.forEach( i -> images.add( i.independentCopy() ) );
89+
s.masks.forEach( i -> masks.add( i.independentCopy() ) );
90+
overlap = s.overlap;
91+
tempArrayM = TempArray.forPrimitiveType( BYTE );
92+
tempArrayAccM = TempArray.forPrimitiveType( BYTE );
93+
tempArrayI = TempArray.forPrimitiveType( FLOAT );
94+
}
95+
96+
@Override
97+
public void copy( final Interval interval, final Object dest )
98+
{
99+
final BlockInterval blockInterval = BlockInterval.asBlockInterval( interval );
100+
final long[] srcPos = blockInterval.min();
101+
final int[] size = blockInterval.size();
102+
103+
final int len = safeInt( Intervals.numElements( size ) );
104+
105+
final byte[] tmpM = tempArrayM.get( len );
106+
final byte[] accM = tempArrayAccM.get( len );
107+
final float[] tmpI = tempArrayI.get( len );
108+
final float[] fdest = Cast.unchecked( dest );
109+
110+
// algorithm:
111+
// create byte[] accM and fill with 0
112+
// for ( i : overlapping ) {
113+
// get masks(i) into tmpM byte[]
114+
// iterate tmpM[x] and accM[x]
115+
// if tmpM[x] == 1 and accM[x] == 0:
116+
// set accM[x] = i+1
117+
// if any accM was set:
118+
// get images(i) into tmpI float[]
119+
// iterate tmpM[x], tmpI[x] and fdest[x]
120+
// if accM[x] == i+1:
121+
// set fdest[i] = tmpI[x]
122+
// }
123+
// finally, where accM[x] == 0, set fdest[i] = 0
124+
125+
Arrays.fill( accM, ( byte ) 0 );
126+
127+
// final long[] srcMax = new long[ srcPos.length ];
128+
// Arrays.setAll( srcMax, d -> srcPos[ d ] + size[ d ] - 1 );
129+
// final int[] overlapping = overlap.getOverlappingViewIndices( srcPos, srcMax );
130+
// for ( int i : overlapping )
131+
// {
132+
// masks.get( i ).copy( srcPos, tmpM, size );
133+
// final byte flag = ( byte ) ( i + 1 );
134+
// boolean anySet = false;
135+
// for ( int x = 0; x < len; ++x )
136+
// {
137+
// if ( tmpM[ x ] == 1 && accM[ x ] == 0 )
138+
// {
139+
// accM[ x ] = flag;
140+
// anySet = true;
141+
// }
142+
// }
143+
// if ( anySet )
144+
// {
145+
// images.get( i ).copy( srcPos, tmpI, size );
146+
// for ( int x = 0; x < len; ++x )
147+
// {
148+
// if ( accM[ x ] == flag )
149+
// fdest[ x ] = tmpI[ x ];
150+
// }
151+
// }
152+
// }
153+
// for ( int x = 0; x < len; ++x )
154+
// {
155+
// if ( accM[ x ] == 0 )
156+
// fdest[ x ] = 0;
157+
// }
158+
159+
final long[] srcMax = new long[ srcPos.length ];
160+
Arrays.setAll( srcMax, d -> srcPos[ d ] + size[ d ] - 1 );
161+
final int[] overlapping = overlap.getOverlappingViewIndices( srcPos, srcMax );
162+
int remaining = len;
163+
164+
// all we do is iterate in the opposite order
165+
final int[] overlappingReversed = new int[ overlapping.length ];
166+
167+
for ( int i = 0; i < overlapping.length; ++i )
168+
overlappingReversed[ i ] = overlapping[ overlapping.length - 1 - i ];
169+
170+
for ( int i : overlappingReversed )
171+
{
172+
masks.get( i ).copy( blockInterval, tmpM );
173+
final byte flag = ( byte ) ( i + 1 );
174+
final int remainingBefore = remaining;
175+
for ( int x = 0; x < len; ++x )
176+
{
177+
if ( tmpM[ x ] == 1 && accM[ x ] == 0 )
178+
{
179+
accM[ x ] = flag;
180+
--remaining;
181+
}
182+
}
183+
if ( remaining != remainingBefore )
184+
{
185+
images.get( i ).copy( blockInterval, tmpI );
186+
for ( int x = 0; x < len; ++x )
187+
{
188+
if ( accM[ x ] == flag )
189+
fdest[ x ] = tmpI[ x ];
190+
}
191+
}
192+
if ( remaining == 0 )
193+
return;
194+
}
195+
for ( int x = 0; x < len; ++x )
196+
{
197+
if ( accM[ x ] == 0 )
198+
fdest[ x ] = 0;
199+
}
200+
201+
// TODO
202+
// alternative to try:
203+
// count down remaining accM[x]==0 from len
204+
// when remaining==0 stop
205+
// if after all masks remaining>0, then where accM[x] == 0, set fdest[i] = 0
206+
}
207+
208+
@Override
209+
public BlockSupplier< FloatType > independentCopy()
210+
{
211+
return new FirstWinsBlockSupplier( this );
212+
}
213+
214+
@Override
215+
public int numDimensions()
216+
{
217+
return numDimensions;
218+
}
219+
220+
private static final FloatType type = new FloatType();
221+
222+
@Override
223+
public FloatType getType()
224+
{
225+
return type;
226+
}
227+
}
228+
}

0 commit comments

Comments
 (0)