/*- * #%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 static mpicbg.spim.data.generic.sequence.ImgLoaderHints.LOAD_COMPLETELY; import java.util.ArrayList; import java.util.List; import mpicbg.spim.data.sequence.Channel; import mpicbg.spim.data.sequence.ImgLoader; import mpicbg.spim.data.sequence.TimePoint; import mpicbg.spim.data.sequence.ViewDescription; import mpicbg.spim.data.sequence.ViewId; import mpicbg.spim.data.sequence.VoxelDimensions; import net.imglib2.FinalInterval; import net.imglib2.Interval; import net.imglib2.RandomAccessible; import net.imglib2.RandomAccessibleInterval; import net.imglib2.RealRandomAccessible; import net.imglib2.img.Img; import net.imglib2.interpolation.InterpolatorFactory; import net.imglib2.realtransform.AffineTransform3D; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.complex.ComplexFloatType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; import spim.fiji.spimdata.SpimData2; import spim.fiji.spimdata.ViewSetupUtils; import spim.process.fusion.boundingbox.BoundingBoxGUI; import spim.process.fusion.weights.Blending; import spim.process.fusion.weights.ContentBased; public abstract class ProcessFusion { public static float[] defaultBlendingRange = new float[]{ 40, 40, 40 }; public static float[] defaultBlendingBorder = new float[]{ 0, 0, 0 }; public static boolean defaultAdjustBlendingForAnisotropy = true; public static double[] defaultContentBasedSigma1 = new double[]{ 20, 20, 20 }; public static double[] defaultContentBasedSigma2 = new double[]{ 40, 40, 40 }; public static boolean defaultAdjustContentBasedSigmaForAnisotropy = true; final protected SpimData2 spimData; final List< ViewId > viewIdsToProcess; final BoundingBoxGUI bb; final boolean useBlending; final boolean useContentBased; public ProcessFusion( final SpimData2 spimData, final List< ViewId > viewIdsToProcess, final BoundingBoxGUI bb, final boolean useBlending, final boolean useContentBased ) { this.spimData = spimData; this.viewIdsToProcess = viewIdsToProcess; this.bb = bb; this.useBlending = useBlending; this.useContentBased = useContentBased; } public abstract < T extends RealType< T > & NativeType< T > > Img< T > fuseStack( final T type, final InterpolatorFactory< T, RandomAccessible< T > > interpolatorFactory, final TimePoint timepoint, final Channel channel ); protected Blending getBlending( final Interval interval, final ViewDescription desc, final ImgLoader imgLoader ) { final float[] blending = ProcessFusion.defaultBlendingRange.clone(); final float[] border = ProcessFusion.defaultBlendingBorder.clone(); final float minRes = (float)getMinRes( desc, imgLoader ); final VoxelDimensions voxelSize = ViewSetupUtils.getVoxelSizeOrLoad( desc.getViewSetup(), desc.getTimePoint(), imgLoader ); if ( ProcessFusion.defaultAdjustBlendingForAnisotropy ) { for ( int d = 0; d < 2; ++d ) { blending[ d ] /= ( float ) voxelSize.dimension( d ) / minRes; border[ d ] /= ( float ) voxelSize.dimension( d ) / minRes; } } return new Blending( interval, border, blending ); } protected < T extends RealType< T > > ContentBased< T > getContentBased( final RandomAccessibleInterval< T > img, final ViewDescription desc, final ImgLoader imgLoader ) { final double[] sigma1 = ProcessFusion.defaultContentBasedSigma1.clone(); final double[] sigma2 = ProcessFusion.defaultContentBasedSigma2.clone(); final double minRes = getMinRes( desc, imgLoader ); final VoxelDimensions voxelSize = ViewSetupUtils.getVoxelSizeOrLoad( desc.getViewSetup(), desc.getTimePoint(), imgLoader ); if ( ProcessFusion.defaultAdjustContentBasedSigmaForAnisotropy ) { for ( int d = 0; d < 2; ++d ) { sigma1[ d ] /= voxelSize.dimension( d ) / minRes; sigma2[ d ] /= voxelSize.dimension( d ) / minRes; } } return new ContentBased<T>( img, bb.getImgFactory( new ComplexFloatType() ), sigma1, sigma2); } protected < T extends RealType< T > > ArrayList< RealRandomAccessible< FloatType > > getAllWeights( final RandomAccessibleInterval< T > img, final ViewDescription desc, final ImgLoader imgLoader ) { final ArrayList< RealRandomAccessible< FloatType > > weigheners = new ArrayList< RealRandomAccessible< FloatType > >(); if ( useBlending ) weigheners.add( getBlending( new FinalInterval( img ), desc, imgLoader ) ); if ( useContentBased ) weigheners.add( getContentBased( img, desc, imgLoader ) ); return weigheners; } public static double getMinRes( final ViewDescription desc, final ImgLoader imgLoader ) { final VoxelDimensions size = ViewSetupUtils.getVoxelSizeOrLoad( desc.getViewSetup(), desc.getTimePoint(), imgLoader ); return Math.min( size.dimension( 0 ), Math.min( size.dimension( 1 ), size.dimension( 2 ) ) ); } protected AffineTransform3D getTransform( final ViewDescription inputData ) { return spimData.getViewRegistrations().getViewRegistration( inputData ).getModel(); } protected AffineTransform3D[] getTransforms( final ArrayList< ViewDescription > inputData ) { final int numViews = inputData.size(); final AffineTransform3D[] transforms = new AffineTransform3D[ numViews ]; for ( int i = 0; i < numViews; ++i ) transforms[ i ] = getTransform( inputData.get( i ) ); return transforms; } public static < T extends RealType< T > > RandomAccessibleInterval< T > getImage( final T type, final SpimData2 spimData, final ViewId view, final boolean normalize ) { return getImage( type, spimData.getSequenceDescription().getImgLoader(), view, normalize ); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static < T extends RealType< T > > RandomAccessibleInterval< T > getImage( final T type, ImgLoader imgLoader, final ViewId view, final boolean normalize ) { if ( (RealType)type instanceof FloatType ) return (RandomAccessibleInterval)imgLoader.getSetupImgLoader( view.getViewSetupId() ).getFloatImage( view.getTimePointId(), normalize, LOAD_COMPLETELY ); else if ( (RealType)type instanceof UnsignedShortType ) return (RandomAccessibleInterval)imgLoader.getSetupImgLoader( view.getViewSetupId() ).getImage( view.getTimePointId(), LOAD_COMPLETELY ); else return null; } }