@Override public void run() { if (fast && forward) { FFTMethods.dimensionsRealToComplexFast(inputDimensions, paddedSize, fftSize); } else if (!fast && forward) { FFTMethods.dimensionsRealToComplexSmall(inputDimensions, paddedSize, fftSize); } if (fast && !forward) { FFTMethods.dimensionsComplexToRealFast(inputDimensions, paddedSize, fftSize); } else if (!fast && !forward) { FFTMethods.dimensionsComplexToRealSmall(inputDimensions, paddedSize, fftSize); } }
final public static < C extends ComplexType< C >, R extends RealType< R > > void complexToRealUnpad( final RandomAccessibleInterval< C > input, final RandomAccessibleInterval< R > output, final ExecutorService service ) { for ( int d = 1; d < input.numDimensions(); ++d ) FFTMethods.complexToComplex( input, d, false, true, service ); FFTMethods.complexToReal( input, output, FFTMethods.unpaddingIntervalCentered( input, output ), 0, true, service ); }
final public static < R extends RealType< R >, C extends ComplexType< C > > void realToComplex( final RandomAccessibleInterval< R > input, final RandomAccessibleInterval< C > output ) { FFTMethods.realToComplex( input, output, 0 ); for ( int d = 1; d < input.numDimensions(); ++d ) FFTMethods.complexToComplex( output, d, true ); }
/** * Calculates padding size and complex FFT size for real to complex FFT * * @param fast if true calculate size for fast FFT * @param inputDimensions original real dimensions * @param paddedDimensions padded real dimensions * @param fftDimensions complex FFT dimensions */ public static void dimensionsRealToComplex(final boolean fast, final Dimensions inputDimensions, final long[] paddedDimensions, final long[] fftDimensions) { if (fast) { FFTMethods.dimensionsRealToComplexFast(inputDimensions, paddedDimensions, fftDimensions); } else { FFTMethods.dimensionsRealToComplexSmall(inputDimensions, paddedDimensions, fftDimensions); } }
final long[] realDimensions = new long[ numDimensions ]; FFTMethods.dimensionsComplexToRealFast( inputInterval, paddedDimensions, realDimensions ); if ( !FFTMethods.dimensionsEqual( inputInterval, paddedDimensions ) ) inputInterval = FFTMethods.paddingIntervalCentered( inputInterval, FinalDimensions.wrap( paddedDimensions ) ); FFTMethods.complexToComplex( fft, d, false ); FFTMethods.complexToReal( fft, output, 0 ); FFTMethods.complexToComplex( fft, d, false ); FFTMethods.complexToReal( fft, output, FFTMethods.unpaddingIntervalCentered( inputInterval, outputDimensions ), 0 );
public static Pair< Interval, Interval > setupFFTs( final Interval imgInterval, final Interval kernelInterval, final long[] min, final long[] max ) { final int numDimensions = imgInterval.numDimensions(); // the image has to be extended at least by kernelDimensions/2-1 in each // dimension so that // the pixels outside of the interval are used for the convolution. final long[] newDimensions = new long[ numDimensions ]; for ( int d = 0; d < numDimensions; ++d ) newDimensions[ d ] = ( int ) imgInterval.dimension( d ) + ( int ) kernelInterval.dimension( d ) - 1; // compute the size of the complex-valued output and the required // padding // based on the prior extended input image final long[] paddedDimensions = new long[ numDimensions ]; final long[] fftDimensions = new long[ numDimensions ]; FFTMethods.dimensionsRealToComplexFast( FinalDimensions.wrap( newDimensions ), paddedDimensions, fftDimensions ); // compute the new interval for the input image final Interval imgConvolutionInterval = FFTMethods.paddingIntervalCentered( imgInterval, FinalDimensions.wrap( paddedDimensions ) ); // compute the new interval for the kernel image final Interval kernelConvolutionInterval = FFTMethods.paddingIntervalCentered( kernelInterval, FinalDimensions.wrap( paddedDimensions ) ); // compute where to place the final Interval for the kernel so that the // coordinate in the center // of the kernel is at position (0,0) for ( int d = 0; d < numDimensions; ++d ) { min[ d ] = kernelInterval.min( d ) + kernelInterval.dimension( d ) / 2; max[ d ] = min[ d ] + kernelConvolutionInterval.dimension( d ) - 1; } return new ValuePair< Interval, Interval >( imgConvolutionInterval, kernelConvolutionInterval ); }
final public static < R extends RealType< R >, C extends ComplexType< C > > Img< C > realToComplex( final RandomAccessible< R > input, Interval inputInterval, final ImgFactory< C > factory, final C type ) { // compute the size of the complex-valued output and the required padding final long[] paddedDimensions = new long[ input.numDimensions() ]; final long[] fftDimensions = new long[ input.numDimensions() ]; FFTMethods.dimensionsRealToComplexFast( inputInterval, paddedDimensions, fftDimensions ); // create the output Img final Img< C > fft = factory.create( fftDimensions, type ); // if the input size is not the right size adjust the interval if ( !FFTMethods.dimensionsEqual( inputInterval, paddedDimensions ) ) inputInterval = FFTMethods.paddingIntervalCentered( inputInterval, FinalDimensions.wrap( paddedDimensions ) ); // real-to-complex fft realToComplex( Views.interval( input, inputInterval ), fft ); return fft; }
/** * Computes a real-to-complex forward FFT transform of an n-dimensional dataset in a certain dimension (typically dim = 0). * By default as many threads as processors are available are used. * By default the complex values are not scaled (not divided by the amount of pixels in the input dataset) * * @param input - the real-valued input dataset * @param output - the complex-valued output dataset * @param dim - the dimension to compute the FFT in * @return - true if successful, false if the dimensions of input and output are not compatible, i.e. not supported by the edu_mines_jtk 1d fft */ final public static < R extends RealType< R >, C extends ComplexType< C > > boolean realToComplex( final RandomAccessibleInterval< R > input, final RandomAccessibleInterval< C > output, final int dim ) { return realToComplex( input, output, output, dim, false ); }
/** * Computes a complex-to-real inverse FFT transform of an n-dimensional dataset in a certain dimension (typically dim = 0). * By default as many threads as processors are available are used. * By default the real values are scaled (divided by the amount of pixels in the input dataset), this way after performing a forward and reverse FFT, the values will be exactly the same * * @param input - the complex-valued input dataset * @param output - the real-valued output dataset * @param dim - the dimension to compute the inverse FFT in * @return - true if successful, false if the dimensions of input and output are not compatible, i.e. not supported by the edu_mines_jtk 1d fft */ final public static < C extends ComplexType< C >, R extends RealType< R > > boolean complexToReal( final RandomAccessibleInterval< C > input, final RandomAccessibleInterval< R > output, final int dim ) { return complexToReal( input, output, output, dim, true ); }
/** * Computes a complex-to-complex forward or inverse FFT transform of an * n-dimensional dataset in a certain dimension. By default as many threads as * processors are available are used. By default the real values are scaled if * it is an inverse transform (divided by the amount of pixels in the input * dataset), this way after performing a forward and reverse FFT, the values * will be exactly the same. By default the real values are not scaled if it * is a forward transform (not divided by the amount of pixels in the input * dataset) * * @param data - the complex-valued dataset (FFT performed in-place) * @param dim - the dimension to compute the inverse FFT in * @param forward - true means forward FFT transform, false means inverse FFT * transform * @return - true if successful, false if the dimensionality of the dataset is * not supported by the edu_mines_jtk 1d fft */ final public static <C extends ComplexType<C>> boolean complexToComplex(final RandomAccessibleInterval<C> data, final int dim, final boolean forward) { if (forward) return complexToComplex(data, dim, forward, false); return complexToComplex(data, dim, forward, true); }
final public static < C extends ComplexType< C >, R extends RealType< R > > void complexToReal( final RandomAccessibleInterval< C > input, final RandomAccessibleInterval< R > output ) { for ( int d = 1; d < input.numDimensions(); ++d ) FFTMethods.complexToComplex( input, d, false ); FFTMethods.complexToReal( input, output, 0 ); }
/** * Make sure that the input size conforms to a supported FFT size. */ @Override public boolean conforms() { long[] paddedDimensions = new long[in().numDimensions()]; long[] realDimensions = new long[in().numDimensions()]; boolean fastSizeConforms = false; FFTMethods.dimensionsComplexToRealFast(in(), paddedDimensions, realDimensions); if (FFTMethods.dimensionsEqual(in(), paddedDimensions) == true) { fastSizeConforms = true; } boolean smallSizeConforms = false; FFTMethods.dimensionsComplexToRealSmall(in(), paddedDimensions, realDimensions); if ((FFTMethods.dimensionsEqual(in(), paddedDimensions) == true)) { smallSizeConforms = true; } return fastSizeConforms || smallSizeConforms; }
/** * Make sure that the input size conforms to a supported FFT size. */ @Override public boolean conforms() { long[] paddedDimensions = new long[in().numDimensions()]; boolean fastSizeConforms = false; FFTMethods.dimensionsComplexToComplexFast(in(), paddedDimensions); if (FFTMethods.dimensionsEqual(in(), paddedDimensions) == true) { fastSizeConforms = true; } boolean smallSizeConforms = false; FFTMethods.dimensionsComplexToComplexSmall(in(), paddedDimensions); if ((FFTMethods.dimensionsEqual(in(), paddedDimensions) == true)) { smallSizeConforms = true; } return fastSizeConforms || smallSizeConforms; }
@Override @SuppressWarnings("unchecked") public O calculate(final I input, final Dimensions paddedDimensions) { final long[] paddedSize = new long[paddedDimensions.numDimensions()]; paddedDimensions.dimensions(paddedSize); O inputInterval = (O) FFTMethods.paddingIntervalCentered(input, FinalDimensions.wrap(paddedSize)); return inputInterval; } }
if (!verifyComplexToComplexfftDimensions(dataSize[dim], dataSize[dim])) { System.out .println("Unsupported combination of dimensionality of input and output"); computeComplexToComplex1dFFT(fft, forward, randomAccess, dim, tempIn, tempOut, scale);
public static < R extends RealType< R > > Img< ComplexFloatType > computeKernelFFT( final Interval kernelConvolutionInterval, final long[] min, final long[] max, final boolean complexConjugate, final RandomAccessible< R > kernel, final ImgFactory< ComplexFloatType > fftFactory, final ExecutorService service ) { // assemble the correct kernel (size of the input + extended periodic + // top left at center of input kernel) final RandomAccessibleInterval< R > kernelInput = Views.interval( Views.extendPeriodic( Views.interval( kernel, kernelConvolutionInterval ) ), new FinalInterval( min, max ) ); final Img< ComplexFloatType > fftKernel = FFT.realToComplex( kernelInput, fftFactory, service ); // if complexConjugate is set we are computing the correlation // instead of the convolution (same as mirroring the kernel) // should be false by default if ( complexConjugate ) FFTMethods.complexConjugate( fftKernel ); return fftKernel; }
final long[] realDimensions = new long[ numDimensions ]; FFTMethods.dimensionsComplexToRealFast( inputInterval, paddedDimensions, realDimensions ); if ( !FFTMethods.dimensionsEqual( inputInterval, paddedDimensions ) ) inputInterval = FFTMethods.paddingIntervalCentered( inputInterval, FinalDimensions.wrap( paddedDimensions ) ); FFTMethods.complexToComplex( fft, d, false ); FFTMethods.complexToReal( fft, output, 0, true, service ); FFTMethods.complexToComplex( fft, d, false, true, service ); FFTMethods.complexToReal( fft, output, FFTMethods.unpaddingIntervalCentered( inputInterval, outputDimensions ), 0, true, service );
public static Pair< Interval, Interval > setupFFTs( final Interval imgInterval, final Interval kernelInterval, final long[] min, final long[] max ) { final int numDimensions = imgInterval.numDimensions(); // the image has to be extended at least by kernelDimensions/2-1 in each // dimension so that // the pixels outside of the interval are used for the convolution. final long[] newDimensions = new long[ numDimensions ]; for ( int d = 0; d < numDimensions; ++d ) newDimensions[ d ] = ( int ) imgInterval.dimension( d ) + ( int ) kernelInterval.dimension( d ) - 1; // compute the size of the complex-valued output and the required // padding // based on the prior extended input image final long[] paddedDimensions = new long[ numDimensions ]; final long[] fftDimensions = new long[ numDimensions ]; FFTMethods.dimensionsRealToComplexFast( FinalDimensions.wrap( newDimensions ), paddedDimensions, fftDimensions ); // compute the new interval for the input image final Interval imgConvolutionInterval = FFTMethods.paddingIntervalCentered( imgInterval, FinalDimensions.wrap( paddedDimensions ) ); // compute the new interval for the kernel image final Interval kernelConvolutionInterval = FFTMethods.paddingIntervalCentered( kernelInterval, FinalDimensions.wrap( paddedDimensions ) ); // compute where to place the final Interval for the kernel so that the // coordinate in the center // of the kernel is at position (0,0) for ( int d = 0; d < numDimensions; ++d ) { min[ d ] = kernelInterval.min( d ) + kernelInterval.dimension( d ) / 2; max[ d ] = min[ d ] + kernelConvolutionInterval.dimension( d ) - 1; } return new ValuePair< Interval, Interval >( imgConvolutionInterval, kernelConvolutionInterval ); }
final public static < R extends RealType< R >, C extends ComplexType< C > > Img< C > realToComplex( final RandomAccessible< R > input, Interval inputInterval, final ImgFactory< C > factory, final ExecutorService service ) { // compute the size of the complex-valued output and the required // padding final long[] paddedDimensions = new long[ input.numDimensions() ]; final long[] fftDimensions = new long[ input.numDimensions() ]; FFTMethods.dimensionsRealToComplexFast( inputInterval, paddedDimensions, fftDimensions ); // create the output Img final Img< C > fft = factory.create( fftDimensions ); // if the input size is not the right size adjust the interval if ( !FFTMethods.dimensionsEqual( inputInterval, paddedDimensions ) ) inputInterval = FFTMethods.paddingIntervalCentered( inputInterval, FinalDimensions.wrap( paddedDimensions ) ); // real-to-complex fft realToComplex( Views.interval( input, inputInterval ), fft, service ); return fft; }
/** * Computes a real-to-complex forward FFT transform of an n-dimensional dataset in a certain dimension (typically dim = 0). * * @param input - the real-valued input dataset * @param output - the complex-valued output dataset * @param dim - the dimension to compute the FFT in * @param scale - define if each pixel is divided by the sum of all pixels in the image * @param numThreads - the number of threads used for the computation (if dataset is more than 1-dimensional) * @return - true if successful, false if the dimensions of input and output are not compatible, i.e. not supported by the edu_mines_jtk 1d fft */ final public static < R extends RealType< R >, C extends ComplexType< C > > boolean realToComplex( final RandomAccessibleInterval< R > input, final RandomAccessibleInterval< C > output, final int dim, final boolean scale, final int numThreads ) { return realToComplex( input, output, output, dim, scale, numThreads ); }