net.imglib2.RealInterval Java Examples

The following examples show how to use net.imglib2.RealInterval. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TransformTools.java    From BigStitcher with GNU General Public License v2.0 6 votes vote down vote up
public static FinalRealInterval getOverlap(final RealInterval img1, final RealInterval img2){
	final int n = img1.numDimensions();
	final double [] min = new double [n];
	final double [] max = new double [n];
	
	for (int i = 0; i< n; i++)
	{
		min[i] = Math.max(img1.realMin(i), img2.realMin(i));
		max[i] = Math.min(img1.realMax(i), img2.realMax(i));
		
		// intervals do not overlap
		if ( max[i] < min [i])
			return null;
	}
	
	return new FinalRealInterval(min, max);
}
 
Example #2
Source File: TransformTools.java    From BigStitcher with GNU General Public License v2.0 6 votes vote down vote up
/**
 * create an integer interval from real interval, being conservatie on the size
 * (min is ceiled, max is floored)
 * @param overlap real input
 * @return interger interval, with mins ceiled and maxs floored
 */
public static FinalInterval getLocalRasterOverlap(RealInterval overlap)
{
	final int n = overlap.numDimensions();
	final long [] min = new long [n];
	final long [] max = new long [n];
	
	for (int i = 0; i< n; i++)
	{
		// round down errors when it is exactly 0.5, if we do not do this we end up with two intervals
		// of different size, e.g.:
		// if the first interval starts at 139.5 going to 199, the second one at 0.0 going to 59.5
		// then the rastered 1st would go from round(139.5)=140 + 1 = 141 -to- round(199)=199 - 1 = 198, dim=58
		// and  the rastered 2nd would go from round(0.0)=0 + 1     =   1 -to- round(59.5)=60 - 1 = 59,  dim=59
		min[i] = Math.round((overlap.realMin(i) - 0.0001 )) + 1;
		max[i] = Math.round((overlap.realMax(i) + 0.0001 )) - 1;
	}
	
	return new FinalInterval(min, max);
}
 
Example #3
Source File: ViewerPanelFX.java    From paintera with GNU General Public License v2.0 6 votes vote down vote up
private void setRenderedImageListener()
{
	renderUnit.getRenderedImageProperty().addListener((obs, oldv, newv) -> {
		if (newv != null && newv.getImage() != null) {
			final Interval screenInterval = newv.getScreenInterval();
			final RealInterval renderTargetRealInterval = newv.getRenderTargetRealInterval();
			canvasPane.getCanvas().getGraphicsContext2D().drawImage(
				newv.getImage(), // src
				renderTargetRealInterval.realMin(0), // src X
				renderTargetRealInterval.realMin(1), // src Y
				renderTargetRealInterval.realMax(0) - renderTargetRealInterval.realMin(0), // src width
				renderTargetRealInterval.realMax(1) - renderTargetRealInterval.realMin(1), // src height
				screenInterval.min(0), // dst X
				screenInterval.min(1), // dst Y
				screenInterval.dimension(0), // dst width
				screenInterval.dimension(1)  // dst height
			);
		}
	});
}
 
Example #4
Source File: TransformTools.java    From BigStitcher with GNU General Public License v2.0 6 votes vote down vote up
public static FinalRealInterval applyTranslation(RealInterval img, TranslationGet translation, boolean[] ignoreDims){

		// get number of dimensions we actually use
		int n = 0;
		for (int d = 0; d < ignoreDims.length; ++d)
			if (!ignoreDims[d])
				n++;
		
		final double [] min = new double [n];
		final double [] max = new double [n];
		
		int i2 = 0;
		for (int i = 0; i< img.numDimensions();++i)
		{
			if (!ignoreDims[i])
			{
				min[i2] = img.realMin(i) + translation.getTranslation(i);
				max[i2] = img.realMax(i) + translation.getTranslation(i);
				i2++;
			}
		}
		return new FinalRealInterval(min, max);
	}
 
Example #5
Source File: RenderUnit.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
public RenderResult(
		final Image image,
		final Interval screenInterval,
		final RealInterval renderTargetRealInterval,
		final int screenScaleIndex) {
	this.image = image;
	this.screenInterval = screenInterval;
	this.renderTargetRealInterval = renderTargetRealInterval;
	this.screenScaleIndex = screenScaleIndex;
}
 
Example #6
Source File: ContentBased.java    From SPIM_Registration with GNU General Public License v2.0 5 votes vote down vote up
@Override
public RealRandomAccess<FloatType> realRandomAccess( final RealInterval interval )
{
	return Views.interpolate(
			Views.extendZero( this.contentBasedImg ),
			new NLinearInterpolatorFactory< FloatType >()
			).realRandomAccess( interval );
}
 
Example #7
Source File: TransformTools.java    From BigStitcher with GNU General Public License v2.0 5 votes vote down vote up
/**
 * get overlap in local image coordinates (assuming min = (0,0,..))
 * @param img image interval (global coordinates)
 * @param overlap overlap interval (global coordinates)
 * @return overlap interval  in local coordinates
 */
public static FinalRealInterval getLocalOverlap(RealInterval img, RealInterval overlap){
	final int n = img.numDimensions();
	final double [] min = new double [n];
	final double [] max = new double [n];
	
	for (int i = 0; i< n; i++)
	{
		min[i] = Math.max(0, overlap.realMin(i) - img.realMin(i)) ;
		max[i] = Math.max(0, overlap.realMax(i) - img.realMin(i));
	}
	return new FinalRealInterval(min, max);
}
 
Example #8
Source File: AbstractRealOutOfBoundsValue.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
public < F extends RealInterval & RealRandomAccessible< T > > AbstractRealOutOfBoundsValue( final F f )
{
	super( f.numDimensions() );
	this.sampler = f.realRandomAccess();
	min = new double[ n ];
	f.realMin( min );
	max = new double[ n ];
	f.realMax( max );
	dimIsOutOfBounds = new boolean[ n ];
}
 
Example #9
Source File: Grids.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Get all blocks/cells of a {@link CellGrid} that the real interval defined by {@code min} and {@code max}
 * intersects with, represented as linear indices.
 * @param interval interval
 * @param cellGrid defines grid (block size/cell size)
 * @return linear indices of all cells/blocks that intersect with interval defined by {@code min}, {@code max}.
 */
public static long[] getIntersectingBlocks(
		final RealInterval interval,
		final CellGrid cellGrid)
{
	return getIntersectingBlocks(
			Intervals.minAsDoubleArray(interval),
			Intervals.maxAsDoubleArray(interval),
			cellGrid
		);
}
 
Example #10
Source File: MeshGeneratorJobManager.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
private Node createBlockShape(final ShapeKey<T> key)
	{
		final Interval keyInterval = key.interval();
		final double[] worldMin = new double[3], worldMax = new double[3];
		Arrays.setAll(worldMin, d -> keyInterval.min(d));
		Arrays.setAll(worldMax, d -> keyInterval.min(d) + keyInterval.dimension(d));
		unshiftedWorldTransforms.apply(key.scaleIndex()).apply(worldMin, worldMin);
		unshiftedWorldTransforms.apply(key.scaleIndex()).apply(worldMax, worldMax);

		final RealInterval blockWorldInterval = new FinalRealInterval(worldMin, worldMax);
		final double[] blockWorldSize = new double[blockWorldInterval.numDimensions()];
		Arrays.setAll(blockWorldSize, d -> blockWorldInterval.realMax(d) - blockWorldInterval.realMin(d));

		// the standard Box primitive is made up of triangles, so the unwanted diagonals are visible when using DrawMode.Line
//		final Box box = new Box(
//				blockWorldSize[0],
//				blockWorldSize[1],
//				blockWorldSize[2]
//			);
		final PolygonMeshView box = new PolygonMeshView(Meshes.createQuadrilateralMesh(
				(float) blockWorldSize[0],
				(float) blockWorldSize[1],
				(float) blockWorldSize[2]
		));

		final double[] blockWorldTranslation = new double[blockWorldInterval.numDimensions()];
		Arrays.setAll(blockWorldTranslation, d -> blockWorldInterval.realMin(d) + blockWorldSize[d] * 0.5);

		box.setTranslateX(blockWorldTranslation[0]);
		box.setTranslateY(blockWorldTranslation[1]);
		box.setTranslateZ(blockWorldTranslation[2]);

		final PhongMaterial material = Meshes.painteraPhongMaterial();
		box.setCullFace(CullFace.NONE);
		box.setMaterial(material);
		box.setDrawMode(DrawMode.LINE);

		return box;
	}
 
Example #11
Source File: MaskedSource.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
@Override
public RealRandomAccessible<D> getInterpolatedDataSource(final int t, final int level, final Interpolation method)
{
	final RealRandomAccessible<D> dataSourceToExtend;

	// ignore interpolation method because we cannot use linear interpolation on LabelMultisetType
	final RealRandomAccessible<D> interpolatedDataSource = this.source.getInterpolatedDataSource(t, level, Interpolation.NEARESTNEIGHBOR);
	if (!this.showCanvasOverBackground.get() || this.affectedBlocks.size() == 0 && this.currentMask == null)
	{
		LOG.debug("Hide canvas or no mask/canvas data present -- delegate to underlying source");
		dataSourceToExtend = interpolatedDataSource;
	}
	else
	{
		final RealRandomAccessible<UnsignedLongType> dataCanvas = interpolateNearestNeighbor(Views.extendValue(this.dataCanvases[level], new UnsignedLongType(Label.INVALID)));
		final RealRandomAccessible<UnsignedLongType> dataMask = this.dMasks[level];
		final RealRandomAccessibleTriple<D, UnsignedLongType, UnsignedLongType> composed = new RealRandomAccessibleTriple<>(
				interpolatedDataSource,
				dataCanvas,
				dataMask);
		dataSourceToExtend = new PickOne<>(composed, pacD.copyWithDifferentNumOccurences(numContainedVoxels(level)));
	}

	// extend the interpolated source with the specified out of bounds value
	final RealInterval bounds = new FinalRealInterval(source.getDataSource(t, level));
	final RealRandomAccessibleRealInterval<D> boundedDataSource = new FinalRealRandomAccessibleRealInterval<>(dataSourceToExtend, bounds);
	return new ExtendedRealRandomAccessibleRealInterval<>(boundedDataSource, new RealOutOfBoundsConstantValueFactory<>(extensionD.copy()));
}
 
Example #12
Source File: ViewFrustum.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
public RealInterval viewPlaneAtGivenDistance(final double z)
{
	final double[] min = new double[2], max = new double[2];
	for (int d = 0; d < 2; ++d)
	{
		final double halfLen = tanHalfFov[d] * z;
		min[d] = -halfLen;
		max[d] = +halfLen;
	}
	return new FinalRealInterval(min, max);
}
 
Example #13
Source File: ViewFrustum.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
public ViewFrustum(final PerspectiveCamera camera, final double[] screenSize)
{
	this.screenSize = screenSize.clone();
	this.tanHalfFov = new double[2];

	final double widthToHeightRatio = screenSize[0] / screenSize[1];
	final double halfFovMainDimension = Math.toRadians(camera.getFieldOfView() / 2);
	if (camera.isVerticalFieldOfView())
	{
		tanHalfFov[1] = Math.tan(halfFovMainDimension);
		tanHalfFov[0] = tanHalfFov[1] * widthToHeightRatio;
	}
	else
	{
		tanHalfFov[0] = Math.tan(halfFovMainDimension);
		tanHalfFov[1] = tanHalfFov[0] / widthToHeightRatio;
	}

	final ViewFrustumPlane[] newNearFarPlanes = new ViewFrustumPlane[2];
	final double[] clipValues = {camera.getNearClip(), camera.getFarClip()};
	for (int i = 0; i < 2; ++i)
	{
		final double clipVal = clipValues[i];
		final RealInterval viewPlane2D = viewPlaneAtGivenDistance(clipVal);
		newNearFarPlanes[i] = new ViewFrustumPlane();
		newNearFarPlanes[i].minMin.setPosition(new double[] {viewPlane2D.realMin(0), viewPlane2D.realMin(1), clipVal});
		newNearFarPlanes[i].minMax.setPosition(new double[] {viewPlane2D.realMin(0), viewPlane2D.realMax(1), clipVal});
		newNearFarPlanes[i].maxMin.setPosition(new double[] {viewPlane2D.realMax(0), viewPlane2D.realMin(1), clipVal});
		newNearFarPlanes[i].maxMax.setPosition(new double[] {viewPlane2D.realMax(0), viewPlane2D.realMax(1), clipVal});
	}

	nearFarPlanes = new ViewFrustumPlanes(
			newNearFarPlanes[0],
			newNearFarPlanes[1]
		);
}
 
Example #14
Source File: PaintClickOrDrag.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
private synchronized void paint(final double viewerX, final double viewerY)
{

	LOG.debug( "At {} {}", viewerX, viewerY );

	if (!this.isPainting) {
		LOG.debug("Not currently activated for painting, returning without action");
		return;
	}

	final RandomAccessibleInterval<UnsignedLongType> mask = getMaskIfIsPaintingOrNull();
	if (mask == null) {
		LOG.debug("Current mask is null, returning without action");
		return;
	}
	final double radius = brushRadius.getAsDouble();
	final Interval trackedInterval = Paint2D.paint(
			Views.extendValue(mask, new UnsignedLongType(Label.INVALID)),
			this.fillLabel,
			viewerX,
			viewerY,
			radius,
			brushDepth.getAsDouble(),
			labelToViewerTransform,
			globalToViewerTransform,
			labelToGlobalTransform);
	this.interval = this.interval == null
			? trackedInterval
			: Intervals.union(trackedInterval, this.interval);
	++this.fillLabel;

	final RealInterval trackedIntervalInGlobalSpace = IntervalHelpers.extendAndTransformBoundingBox(trackedInterval, labelToGlobalTransform, 0.5);
	this.paintera.orthogonalViews().requestRepaint(trackedIntervalInGlobalSpace);

}
 
Example #15
Source File: ShapeInterpolationMode.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
private RandomAccessibleInterval<UnsignedLongType> getTransformedMaskSection(final SectionInfo sectionInfo)
{
	final RealInterval sectionBounds = sectionInfo.sourceToDisplayTransform.estimateBounds(sectionInfo.sourceBoundingBox);
	final Interval sectionInterval = Intervals.smallestContainingInterval(sectionBounds);
	final RealRandomAccessible<UnsignedLongType> transformedMask = getTransformedMask(sectionInfo.mask, sectionInfo.sourceToDisplayTransform);
	final RandomAccessibleInterval<UnsignedLongType> transformedMaskInterval = Views.interval(Views.raster(transformedMask), sectionInterval);
	return Views.hyperSlice(transformedMaskInterval, 2, 0l);
}
 
Example #16
Source File: MaskedSource.java    From paintera with GNU General Public License v2.0 5 votes vote down vote up
@Override
public RealRandomAccessible<T> getInterpolatedSource(final int t, final int level, final Interpolation method)
{
	final RealRandomAccessible<T> sourceToExtend;

	// ignore interpolation method because we cannot use linear interpolation on LabelMultisetType
	final RealRandomAccessible<T> interpolatedSource = this.source.getInterpolatedSource(t, level, Interpolation.NEARESTNEIGHBOR);
	if (!this.showCanvasOverBackground.get() || this.affectedBlocks.size() == 0 && this.currentMask == null)
	{
		LOG.debug("Hide canvas or no mask/canvas data present -- delegate to underlying source");
		sourceToExtend = interpolatedSource;
	}
	else
	{
		final RealRandomAccessible<VolatileUnsignedLongType> canvas = interpolateNearestNeighbor(Views.extendValue(this.canvases[level].getRai(), new VolatileUnsignedLongType(Label.INVALID)));
		final RealRandomAccessible<VolatileUnsignedLongType> mask = this.tMasks[level];
		final RealRandomAccessibleTriple<T, VolatileUnsignedLongType, VolatileUnsignedLongType> composed = new
				RealRandomAccessibleTriple<>(
				interpolatedSource,
				canvas,
				mask
		);
		sourceToExtend = new PickOne<>(composed, pacT.copyWithDifferentNumOccurences(numContainedVoxels(level)));
	}

	// extend the interpolated source with the specified out of bounds value
	final RealInterval bounds = new FinalRealInterval(source.getSource(t, level));
	final RealRandomAccessibleRealInterval<T> boundedSource = new FinalRealRandomAccessibleRealInterval<>(sourceToExtend, bounds);
	return new ExtendedRealRandomAccessibleRealInterval<>(boundedSource, new RealOutOfBoundsConstantValueFactory<>(extensionT.copy()));
}
 
Example #17
Source File: MultiResolutionRendererGeneric.java    From paintera with GNU General Public License v2.0 4 votes vote down vote up
public synchronized RealInterval getLastRenderTargetRealInterval()
{
	return lastRenderTargetRealInterval;
}
 
Example #18
Source File: Blending.java    From SPIM_Registration with GNU General Public License v2.0 4 votes vote down vote up
@Override
public RealRandomAccess<FloatType> realRandomAccess( final RealInterval interval )
{
	return realRandomAccess();
}
 
Example #19
Source File: RenderUnit.java    From paintera with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void paint()
{
	final List<SourceAndConverter<?>> sacs = new ArrayList<>();
	final AffineTransform3D viewerTransform = new AffineTransform3D();
	final int timepoint;
	synchronized (RenderUnit.this)
	{
		if (renderer != null && renderTarget != null)
		{
			final ViewerState viewerState = RenderUnit.this.viewerState.get();
			synchronized (viewerState)
			{
				viewerState.getViewerTransform(viewerTransform);
				timepoint = viewerState.getTimepoint();
				sacs.addAll(viewerState.getSources());
			}
		}
		else
		{
			return;
		}
	}

	final int renderedScreenScaleIndex = renderer.paint(
		sacs,
		timepoint,
		viewerTransform,
		interpolation,
		null
	);

	if (renderedScreenScaleIndex != -1)
	{
		final Interval screenInterval = renderer.getLastRenderedScreenInterval();
		final RealInterval renderTargetRealInterval = renderer.getLastRenderTargetRealInterval();

		renderTarget.drawOverlays(img -> renderResultProperty.set(new RenderResult(
			img,
			screenInterval,
			renderTargetRealInterval,
			renderedScreenScaleIndex
		)));
	}
}
 
Example #20
Source File: ExtractPSF.java    From SPIM_Registration with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Transforms the extracted PSF using the affine transformation of the corresponding view
 * 
 * @param psf - the extracted psf (NOT z-scaling corrected)
 * @param model - the transformation model
 * @return the transformed psf which has odd sizes and where the center of the psf is also the center of the transformed psf
 */
protected static < T extends RealType< T > & NativeType< T > > ArrayImg< T, ? > transformPSF(
		final RandomAccessibleInterval< T > psf,
		final AffineTransform3D model )
{
	// here we compute a slightly different transformation than the ImageTransform does
	// two things are necessary:
	// a) the center pixel stays the center pixel
	// b) the transformed psf has a odd size in all dimensions
	
	final int numDimensions = psf.numDimensions();
	
	final RealInterval minMaxDim = model.estimateBounds( psf );
	
	final double[] size = new double[ numDimensions ];		
	final long[] newSize = new long[ numDimensions ];		
	final double[] offset = new double[ numDimensions ];
	
	// the center of the psf has to be the center of the transformed psf as well
	// this is important!
	final double[] center = new double[ numDimensions ];
	final double[] tmp = new double[ numDimensions ];

	for ( int d = 0; d < numDimensions; ++d )
		center[ d ] = psf.dimension( d ) / 2;
	
	model.apply( center, tmp );

	for ( int d = 0; d < numDimensions; ++d )
	{
		size[ d ] = minMaxDim.realMax( d ) - minMaxDim.realMin( d );
		
		newSize[ d ] = (int)size[ d ] + 1;
		if ( newSize[ d ] % 2 == 0 )
			++newSize[ d ];
			
		// the offset is defined like this:
		// the transformed coordinates of the center of the psf
		// are the center of the transformed psf
		offset[ d ] = tmp[ d ] - newSize[ d ]/2;
	}
	
	return transform( psf, model, newSize, offset );
}
 
Example #21
Source File: DefaultDetectJunctions.java    From imagej-ops with BSD 2-Clause "Simplified" License 4 votes vote down vote up
private static Interval slightlyEnlarge(RealInterval realInterval,
	long border)
{
	return Intervals.expand(Intervals.smallestContainingInterval(realInterval),
		border);
}
 
Example #22
Source File: Blending.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
@Override
public RealRandomAccess<FloatType> realRandomAccess( final RealInterval interval )
{
	return realRandomAccess();
}
 
Example #23
Source File: JuliaRealRandomAccessible.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
@Override
public JuliaRealRandomAccess realRandomAccess( final RealInterval interval )
{
	return realRandomAccess();
}
 
Example #24
Source File: TransformationTools.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
public static < T extends RealType< T > > Pair<Pair< AffineGet, Double >, RealInterval> computeStitchingLucasKanade(
		final Group<? extends ViewId> viewIdsA,
		final Group<? extends ViewId> viewIdsB,
		final ViewRegistrations vrs,
		final LucasKanadeParameters params,
		final AbstractSequenceDescription< ?,? extends BasicViewDescription<?>, ? > sd,
		final GroupedViewAggregator gva,
		final long[] downsampleFactors,
		final ExecutorService service )
{
	
	// the transformation that maps the downsampled image coordinates back to the original input(!) image space
	final AffineTransform3D dsCorrectionT1 = new AffineTransform3D();
	final AffineTransform3D dsCorrectionT2 = new AffineTransform3D();

	// get Overlap Bounding Box
	final List<List<ViewId>> views = new ArrayList<>();
	views.add( new ArrayList<>(viewIdsA.getViews()) );
	views.add( new ArrayList<>(viewIdsB.getViews()) );
	BoundingBoxMaximalGroupOverlap< ViewId > bbDet = new BoundingBoxMaximalGroupOverlap<ViewId>( views, sd, vrs );
	BoundingBox bbOverlap = bbDet.estimate( "Max Overlap" );

	// this should be caught outside of this method already, but check nonetheless
	if (bbOverlap == null)
		return null;

	// get one image per group
	final RandomAccessibleInterval<T> img1 = gva.aggregate( viewIdsA, sd, downsampleFactors, dsCorrectionT1 );	
	final RandomAccessibleInterval<T> img2 = gva.aggregate( viewIdsB, sd, downsampleFactors, dsCorrectionT2 );

	if (img1 == null || img2 == null)
	{
		IOFunctions.println( "WARNING: Tried to open missing View when computing Stitching for " + viewIdsA + " and " + 
					viewIdsB + ". No link between those could be determined");
		return null;
	}

	// get translations
	// TODO: is the 2d check here meaningful?
	boolean is2d = img1.numDimensions() == 2;
	Pair< AffineGet, TranslationGet > t1 = TransformTools.getInitialTransforms( vrs.getViewRegistration(viewIdsA.iterator().next()), is2d, dsCorrectionT1 );
	Pair< AffineGet, TranslationGet > t2 = TransformTools.getInitialTransforms( vrs.getViewRegistration(viewIdsB.iterator().next()), is2d, dsCorrectionT2 );

	final Pair< AffineTransform, Double > result  = PairwiseStitching.getShiftLucasKanade(  img1, img2, t1.getB(), t2.getB(), params, service );

	if (result == null)
		return null;

	// TODO: is scaling just the translational part okay here?
	for (int i = 0; i< result.getA().numDimensions(); ++i)			
		result.getA().set( result.getA().get(i, result.getA().numDimensions()) * downsampleFactors[i], i, result.getA().numDimensions() ); 

	// TODO (?): Different translational part of downsample Transformations should be considered via TransformTools.getInitialTransforms
	// we probalbly do not have to correct for them ?

	// NB: as we will deal in global coordinates, not pixel coordinates in global optimization,
	// calculate global R' = VT^-1 * R * VT from pixel transformation R 
	ViewRegistration vrOld = vrs.getViewRegistration(viewIdsB.iterator().next());
	AffineTransform3D resTransform = new AffineTransform3D();
	resTransform.set( result.getA().getRowPackedCopy() );
	resTransform.concatenate( vrOld.getModel().inverse() );
	resTransform.preConcatenate( vrOld.getModel() );

	IOFunctions.println("resulting transformation (pixel coordinates): " + Util.printCoordinates(result.getA().getRowPackedCopy()));
	IOFunctions.println("resulting transformation (global coordinates): " + Util.printCoordinates(resTransform.getRowPackedCopy()));

	return new ValuePair<>( new ValuePair<>( resTransform, result.getB() ), bbOverlap );
}
 
Example #25
Source File: TransformationTools.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
public static < T extends RealType< T > > Pair<Pair< AffineGet, Double >, RealInterval> computeStitching(
		final Group<? extends ViewId> viewIdsA,
		final Group<? extends ViewId> viewIdsB,
		final ViewRegistrations vrs,
		final PairwiseStitchingParameters params,
		final AbstractSequenceDescription< ?,? extends BasicViewDescription<?>, ? > sd,
		final GroupedViewAggregator gva,
		final long[] downsampleFactors,
		final ExecutorService service )
{

	// the transformation that maps the downsampled image coordinates back to the original input(!) image space
	final AffineTransform3D dsCorrectionT1 = new AffineTransform3D();
	final AffineTransform3D dsCorrectionT2 = new AffineTransform3D();

	// get Overlap Bounding Box
	final List<List<ViewId>> views = new ArrayList<>();
	views.add( new ArrayList<>(viewIdsA.getViews()) );
	views.add( new ArrayList<>(viewIdsB.getViews()) );
	BoundingBoxMaximalGroupOverlap< ViewId > bbDet = new BoundingBoxMaximalGroupOverlap<ViewId>( views, sd, vrs );
	BoundingBox bbOverlap = bbDet.estimate( "Max Overlap" );

	// this should be caught outside of this method already, but check nonetheless
	if (bbOverlap == null)
		return null;

	// get one image per group
	final RandomAccessibleInterval<T> img1 = gva.aggregate( viewIdsA, sd, downsampleFactors, dsCorrectionT1 );	
	final RandomAccessibleInterval<T> img2 = gva.aggregate( viewIdsB, sd, downsampleFactors, dsCorrectionT2 );

	if (img1 == null || img2 == null)
	{
		IOFunctions.println( "WARNING: Tried to open missing View when computing Stitching for " + viewIdsA + " and " + 
					viewIdsB + ". No link between those could be determined");
		return null;
	}

	// get translations
	// TODO: is the 2d check here meaningful?
	// everything will probably be 3d at this point, since ImgLoaders return 3d images
	boolean is2d = img1.numDimensions() == 2;
	Pair< AffineGet, TranslationGet > t1 = TransformTools.getInitialTransforms( vrs.getViewRegistration(viewIdsA.iterator().next()), is2d, dsCorrectionT1 );
	Pair< AffineGet, TranslationGet > t2 = TransformTools.getInitialTransforms( vrs.getViewRegistration(viewIdsB.iterator().next()), is2d, dsCorrectionT2 );

	final Pair< Translation, Double > result  = PairwiseStitching.getShift( img1, img2, t1.getB(), t2.getB(), params, service );

	if (result == null)
		return null;
	
	for (int i = 0; i< result.getA().numDimensions(); ++i)			
		result.getA().set( result.getA().get(i, result.getA().numDimensions()) * downsampleFactors[i], i ); 

	// TODO (?): Different translational part of downsample Transformations should be considered via TransformTools.getInitialTransforms
	// we probalbly do not have to correct for them ?

	// NB: as we will deal in global coordinates, not pixel coordinates in global optimization,
	// calculate global R' = VT^-1 * R * VT from pixel transformation R 
	ViewRegistration vrOld = vrs.getViewRegistration(viewIdsB.iterator().next());
	AffineTransform3D resTransform = new AffineTransform3D();
	resTransform.set( result.getA().getRowPackedCopy() );
	resTransform.concatenate( vrOld.getModel().inverse() );
	resTransform.preConcatenate( vrOld.getModel() );

	System.out.println("shift (pixel coordinates): " + Util.printCoordinates(result.getA().getTranslationCopy()));
	System.out.println("shift (global coordinates): " + Util.printCoordinates(resTransform.getRowPackedCopy()));
	System.out.print("cross-corr: " + result.getB());

	return new ValuePair<>( new ValuePair<>( resTransform, result.getB() ), bbOverlap );
}
 
Example #26
Source File: TransformationTools.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
public static < T extends RealType< T > > Pair<Pair< AffineGet, Double >, RealInterval> computeStitchingNonEqualTransformationsLucasKanade(
		final Group<? extends ViewId> viewIdsA,
		final Group<? extends ViewId> viewIdsB,
		final ViewRegistrations vrs,
		final LucasKanadeParameters params,
		final AbstractSequenceDescription< ?,? extends BasicViewDescription<?>, ? > sd,
		final GroupedViewAggregator gva,
		final long[] downsampleFactors,
		final ExecutorService service )
{
	final double[] downsampleDbl = new double[downsampleFactors.length];
	for (int d = 0; d < downsampleFactors.length; d++)
		downsampleDbl[d] = downsampleFactors[d];

	// get Overlap Bounding Box
	final List<List<ViewId>> views = new ArrayList<>();
	views.add( new ArrayList<>(viewIdsA.getViews()) );
	views.add( new ArrayList<>(viewIdsB.getViews()) );
	BoundingBoxMaximalGroupOverlap< ViewId > bbDet = new BoundingBoxMaximalGroupOverlap<ViewId>( views, sd, vrs );
	BoundingBox bbOverlap = bbDet.estimate( "Max Overlap" );

	// we could not find overlap -> ignore this pair
	if (bbOverlap == null)
		return null;

	List<RandomAccessibleInterval< FloatType >> raiOverlaps = new ArrayList<>();		
	for (List< ViewId > tileViews : views)
	{
		// wrap every view id (corresponding e.g. to different channels, illums,.. ) in list
		List<List< ViewId >> wrapped = tileViews.stream().map( v -> {
			ArrayList< ViewId > wrp = new ArrayList<ViewId>();
			wrp.add( v );
			return wrp;} ).collect( Collectors.toList() );

		// open all of them "virtually fused"
		List< RandomAccessibleInterval< FloatType > > openFused = 
				DisplayOverlapTestPopup.openVirtuallyFused( sd, vrs, wrapped, bbOverlap, downsampleDbl );

		// aggregate the group into one image
		RandomAccessibleInterval< FloatType > raiI = gva.aggregate( 
				openFused, 
				tileViews,
				sd );

		raiOverlaps.add(raiI);
	}

	// the overlap in both images
	final RandomAccessibleInterval< FloatType > img1 = raiOverlaps.get(0);
	final RandomAccessibleInterval< FloatType > img2 = raiOverlaps.get(1);
	
	// compute phase correlation shift (passing (0,0,..) translations prevents any overlap correction inside)
	final Pair< AffineTransform, Double > result = PairwiseStitching.getShiftLucasKanade(
			img1,
			img2,
			new Translation( img1.numDimensions() ),
			new Translation( img1.numDimensions() ),
			params,
			service );

	if (result == null)
		return null;

	// scale just the translational part
	for (int i = 0; i< result.getA().numDimensions(); ++i)			
		result.getA().set( result.getA().get(i, result.getA().numDimensions()) * downsampleFactors[i], i ); 

	// TODO (?): Different translational part of downsample Transformations should be considered via TransformTools.getInitialTransforms
	// we probalbly do not have to correct for them ?

	final AffineTransform3D vr = vrs.getViewRegistration(viewIdsB.iterator().next()).getModel();		
	final AffineTransform resCorrected = new AffineTransform( result.getA().numDimensions() );
	resCorrected.set( result.getA() );

	IOFunctions.println("resulting transformation: " + Util.printCoordinates(result.getA().getRowPackedCopy()));

	return new ValuePair<>( new ValuePair<>( resCorrected, result.getB() ), bbOverlap );
}
 
Example #27
Source File: TransformationTools.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
public static < T extends RealType< T > > Pair<Pair< AffineGet, Double >, RealInterval> computeStitchingNonEqualTransformations(
		final Group<? extends ViewId> viewIdsA,
		final Group<? extends ViewId> viewIdsB,
		final ViewRegistrations vrs,
		final PairwiseStitchingParameters params,
		final AbstractSequenceDescription< ?,? extends BasicViewDescription<?>, ? > sd,
		final GroupedViewAggregator gva,
		final long[] downsampleFactors,
		final ExecutorService service )
{

	final double[] downsampleDbl = new double[downsampleFactors.length];
	for (int d = 0; d < downsampleFactors.length; d++)
		downsampleDbl[d] = downsampleFactors[d];

	// get Overlap Bounding Box
	final List<List<ViewId>> views = new ArrayList<>();
	views.add( new ArrayList<>(viewIdsA.getViews()) );
	views.add( new ArrayList<>(viewIdsB.getViews()) );
	BoundingBoxMaximalGroupOverlap< ViewId > bbDet = new BoundingBoxMaximalGroupOverlap<ViewId>( views, sd, vrs );
	BoundingBox bbOverlap = bbDet.estimate( "Max Overlap" );

	// we could not find overlap -> ignore this pair
	if (bbOverlap == null)
		return null;

	List<RandomAccessibleInterval< FloatType >> raiOverlaps = new ArrayList<>();		
	for (List< ViewId > tileViews : views)
	{
		// wrap every view id (corresponding e.g. to different channels, illums,.. ) in list
		List<List< ViewId >> wrapped = tileViews.stream().map( v -> {
			ArrayList< ViewId > wrp = new ArrayList<ViewId>();
			wrp.add( v );
			return wrp;} ).collect( Collectors.toList() );

		// open all of them "virtually fused"
		List< RandomAccessibleInterval< FloatType > > openFused = 
				DisplayOverlapTestPopup.openVirtuallyFused( sd, vrs, wrapped, bbOverlap, downsampleDbl );

		// aggregate the group into one image
		RandomAccessibleInterval< FloatType > raiI = gva.aggregate( 
				openFused, 
				tileViews,
				sd );

		raiOverlaps.add(raiI);
	}

	// the overlap in both images
	final RandomAccessibleInterval< FloatType > img1 = raiOverlaps.get(0);
	final RandomAccessibleInterval< FloatType > img2 = raiOverlaps.get(1);
	
	// compute phase correlation shift (passing (0,0,..) translations prevents any overlap correction inside)
	final Pair< Translation, Double > result = PairwiseStitching.getShift(
			img1,
			img2,
			new Translation( img1.numDimensions() ),
			new Translation( img1.numDimensions() ),
			params,
			service );

	if (result == null)
		return null;

	for (int i = 0; i< result.getA().numDimensions(); ++i)			
		result.getA().set( result.getA().get(i, result.getA().numDimensions()) * downsampleFactors[i], i ); 

	// TODO (?): Different translational part of downsample Transformations should be considered via TransformTools.getInitialTransforms
	// we probalbly do not have to correct for them ?
	final AffineTransform3D vr = vrs.getViewRegistration(viewIdsB.iterator().next()).getModel();		
	final AffineTransform resCorrected = new AffineTransform( result.getA().numDimensions() );
	resCorrected.set( result.getA() );

	System.out.println("shift: " + Util.printCoordinates(result.getA().getTranslationCopy()));
	System.out.print("cross-corr: " + result.getB());

	return new ValuePair<>( new ValuePair<>( resCorrected, result.getB() ), bbOverlap );
}
 
Example #28
Source File: RenderUnit.java    From paintera with GNU General Public License v2.0 4 votes vote down vote up
public RealInterval getRenderTargetRealInterval() {
	return renderTargetRealInterval;
}
 
Example #29
Source File: OrthogonalViews.java    From paintera with GNU General Public License v2.0 4 votes vote down vote up
public void requestRepaint(final RealInterval intervalInGlobalSpace)
{
	this.applyToAll(v -> v.requestRepaint(intervalInGlobalSpace));
}
 
Example #30
Source File: Align.java    From BigStitcher with GNU General Public License v2.0 4 votes vote down vote up
public static void main(String[] args)
{
	Img< FloatType > a = ImgLib2Util.openAs32Bit( new File( "73.tif.zip" ) );
	Img< FloatType > b = ImgLib2Util.openAs32Bit( new File( "74.tif.zip" ) );

	TranslationGet t1 = new Translation3D();
	TranslationGet t2 = new Translation3D(460, 0, 0);
	ArrayList< Pair< RealInterval, AffineGet > > views = new ArrayList<Pair<RealInterval, AffineGet>>();
	views.add( new ValuePair< RealInterval, AffineGet >( a, t1 ) );
	views.add( new ValuePair< RealInterval, AffineGet >( b, t2 ) );

	RealInterval overlap = BoundingBoxMaximalGroupOverlap.getMinBoundingIntervalSingle( views );

	final RealInterval transformed1 = TransformTools.applyTranslation( a, t1, new boolean[] {false, false, false} );
	final RealInterval transformed2 = TransformTools.applyTranslation( b, t2, new boolean[] {false, false, false} );

	// get overlap in images' coordinates
	final RealInterval localOverlap1 = TransformTools.getLocalOverlap( transformed1, overlap );
	final RealInterval localOverlap2 = TransformTools.getLocalOverlap( transformed2, overlap );

	// round to integer interval
	final Interval interval1 = TransformTools.getLocalRasterOverlap( localOverlap1 );
	final Interval interval2 = TransformTools.getLocalRasterOverlap( localOverlap2 );

	//final WarpFunction warp = new TranslationWarp(3);
	final WarpFunction warp = new RigidWarp(3);
	//final WarpFunction warp = new AffineWarp( 3 );

	// rotate second image
	AffineTransform3D rot = new AffineTransform3D();
	rot.rotate( 2, 2 * Math.PI / 180 );
	RandomAccessibleInterval< FloatType > rotated = Views.interval(
			RealViews.affine( 
					Views.interpolate( Views.extendBorder( Views.zeroMin( Views.interval( b, interval2 ) ) ), new NLinearInterpolatorFactory<>() ),
					rot.copy() ),
			interval2);

	// show input
	new ImageJ();
	ImageJFunctions.show( Views.interval( a,  interval1 ), "target" );
	ImageJFunctions.show( rotated, "in");

	// downsample input
	RandomAccessibleInterval< FloatType > simple2x1 = Downsample.simple2x( Views.zeroMin( Views.interval( a, interval1 ) ), new ArrayImgFactory<>(), new boolean[] {true, true, false} );
	RandomAccessibleInterval< FloatType > simple2x2 = Downsample.simple2x( Views.zeroMin( Views.interval( rotated, interval2 ) ), new ArrayImgFactory<>(), new boolean[] {true, true, false} );

	// align

	//Align< FloatType > lk = new Align<>( Views.zeroMin( Views.interval( a, interval1 ) ), new ArrayImgFactory<>(), warp );
	Align< FloatType > lk = new Align<>( simple2x1, new ArrayImgFactory<>(), warp );
	//System.out.println( Util.printCoordinates( lk.align( Views.zeroMin( Views.interval( b, interval2 ) ), 100, 0.01 ).getRowPackedCopy() ) );
	//final AffineTransform transform = lk.align( Views.zeroMin( rotated ), 100, 0.01 );
	final AffineTransform transform = lk.align( simple2x2, 100, 0.01 );

	final AffineTransform scale = new AffineTransform( 3 );
	scale.set( 2, 0, 0 );
	scale.set( 1, 1, 1 );

	transform.preConcatenate( scale );

	// transformation matrix
	System.out.println( Util.printCoordinates( transform.getRowPackedCopy() ) );

	// correct input and show
	RandomAccessibleInterval< FloatType > backRotated = Views.interval(
			RealViews.affine( 
					Views.interpolate( Views.extendBorder( Views.zeroMin( Views.interval( b, interval2 ) ) ), new NLinearInterpolatorFactory<>() ),
					rot.copy().preConcatenate( transform ).copy() ),
			interval2);

	ImageJFunctions.show( backRotated, "out" );

	// constructor needs column packed matrix, therefore the transpose
	Matrix mt = new Matrix( transform.getRowPackedCopy(), 4).transpose();
	Matrix rigid = mt.getMatrix( 0, 2, 0, 2 );

	// check whether result is rotation matrix (det == +-1, orthogonal)
	System.out.println( rigid.det() );
	System.out.println( Util.printCoordinates( rigid.times( rigid.transpose() ).getRowPackedCopy() ) );
}