/*-
* #%L
* Fiji distribution of ImageJ for the life sciences.
* %%
* Copyright (C) 2007 - 2017 Fiji developers.
* %%
* This program 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 2 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/gpl-2.0.html>.
* #L%
*/
package spim.process.fusion.weightedavg;
import java.util.ArrayList;
import net.imglib2.Cursor;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.RealRandomAccess;
import net.imglib2.RealRandomAccessible;
import net.imglib2.img.Img;
import net.imglib2.interpolation.InterpolatorFactory;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.real.FloatType;
import net.imglib2.view.Views;
import spim.process.fusion.FusionHelper;
import spim.process.fusion.ImagePortion;
import spim.process.fusion.boundingbox.BoundingBoxGUI;
/**
* Fuse one portion of a paralell fusion, supports many weight functions
*
* @author Stephan Preibisch (stephan.preibisch@gmx.de)
*
* @param <T>
*/
public class ProcessParalellPortionWeights< T extends RealType< T > > extends ProcessParalellPortion< T >
{
final ArrayList< ArrayList< RealRandomAccessible< FloatType > > > weights;
public ProcessParalellPortionWeights(
final ImagePortion portion,
final ArrayList< RandomAccessibleInterval< T > > imgs,
final ArrayList< ArrayList< RealRandomAccessible< FloatType > > > weights,
final InterpolatorFactory< T, RandomAccessible< T > > interpolatorFactory,
final AffineTransform3D[] transforms,
final Img< T > fusedImg,
final BoundingBoxGUI bb )
{
super( portion, imgs, interpolatorFactory, transforms, fusedImg, bb );
this.weights = weights;
}
@Override
public String call() throws Exception
{
final int numViews = imgs.size();
// make the interpolators, weights and get the transformations
final ArrayList< RealRandomAccess< T > > interpolators = new ArrayList< RealRandomAccess< T > >( numViews );
final ArrayList< ArrayList< RealRandomAccess< FloatType > > > weightAccess = new ArrayList< ArrayList< RealRandomAccess< FloatType > > >();
final int[][] imgSizes = new int[ numViews ][ 3 ];
for ( int i = 0; i < numViews; ++i )
{
final RandomAccessibleInterval< T > img = imgs.get( i );
imgSizes[ i ] = new int[]{ (int)img.dimension( 0 ), (int)img.dimension( 1 ), (int)img.dimension( 2 ) };
interpolators.add( Views.interpolate( Views.extendMirrorSingle( img ), interpolatorFactory ).realRandomAccess() );
final ArrayList< RealRandomAccess< FloatType > > list = new ArrayList< RealRandomAccess< FloatType > >();
for ( final RealRandomAccessible< FloatType > rra : weights.get( i ) )
list.add( rra.realRandomAccess() );
weightAccess.add( list );
}
final Cursor< T > cursor = fusedImg.localizingCursor();
final float[] s = new float[ 3 ];
final float[] t = new float[ 3 ];
cursor.jumpFwd( portion.getStartPosition() );
for ( int j = 0; j < portion.getLoopSize(); ++j )
{
// move img cursor forward any get the value (saves one access)
final T v = cursor.next();
cursor.localize( s );
if ( doDownSampling )
{
s[ 0 ] *= downSampling;
s[ 1 ] *= downSampling;
s[ 2 ] *= downSampling;
}
s[ 0 ] += bb.min( 0 );
s[ 1 ] += bb.min( 1 );
s[ 2 ] += bb.min( 2 );
double sum = 0;
double sumW = 0;
for ( int i = 0; i < numViews; ++i )
{
transforms[ i ].applyInverse( t, s );
if ( FusionHelper.intersects( t[ 0 ], t[ 1 ], t[ 2 ], imgSizes[ i ][ 0 ], imgSizes[ i ][ 1 ], imgSizes[ i ][ 2 ] ) )
{
final RealRandomAccess< T > r = interpolators.get( i );
r.setPosition( t );
double w = 1;
for ( final RealRandomAccess< FloatType > weight : weightAccess.get( i ) )
{
weight.setPosition( t );
w *= weight.get().get();
}
sum += r.get().getRealDouble() * w;
sumW += w;
}
}
if ( sumW > 0 )
v.setReal( sum / sumW );
}
return portion + " finished successfully (many weights).";
}
}