public ImagePlus apply()
	{
		final int width = input.getWidth();
		final int height = input.getHeight();
		final int depth = input.getStackSize();

		//final ImagePlus imageOutput = input.duplicate();
		//final ImageStack imageStackOutput = imageOutput.getStack();

		final ImageStack inputStack = input.getStack();
		
		final ImagePlus binaryOutput = input.duplicate();
		final ImageStack binaryStackOutput = binaryOutput.getStack();

		// Initialize binary output image
		// Binarize output image
		for (int k = 0; k < depth; ++k)
			for (int i = 0; i < width; ++i)
				for (int j = 0; j < height; ++j)	        	  
					binaryStackOutput.setVoxel(i, j, k, 1);

		// Apply 3x3x3 maximum filter
		IJ.log("   Maximum filtering...");
		final long t0 = System.currentTimeMillis();
		final double[][][] localMinValues = filterMax3D( input );
		if( null == localMinValues )
			return null;
		final long t1 = System.currentTimeMillis();
		IJ.log("   Filtering took " + (t1-t0) + " ms.");
		
		// find regional maxima
		IJ.showStatus( "Finding regional maxima..." );
		
		final AtomicInteger ai = new AtomicInteger(0);
        final int n_cpus = Prefs.getThreads();
        
        final int dec = (int) Math.ceil((double) depth / (double) n_cpus);
        
        Thread[] threads = ThreadUtil.createThreadArray(n_cpus);
        for (int ithread = 0; ithread < threads.length; ithread++) 
        {
            threads[ithread] = new Thread() {
                public void run() {
                	for (int k = ai.getAndIncrement(); k < n_cpus; k = ai.getAndIncrement()) 
                	{
                		int zmin = dec * k;
                		int zmax = dec * ( k + 1 );
                		if (zmin<0)
                            zmin = 0;
                        if (zmax > depth)
                            zmax = depth;
                        
                        findMaximaRange( zmin, zmax, inputStack,
                				binaryStackOutput, localMinValues );
                		
                    }
                }
            };
        }
        ThreadUtil.startAndJoin(threads);
		

		IJ.showProgress(1.0);
		
		//(new ImagePlus("valued maxima", imageStackOutput)).show();
		
		return new ImagePlus("regional-maxima-" + input.getTitle(), binaryStackOutput);
	} //apply