/*- * #%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 mpicbg.spim.registration.detection.descriptor; import fiji.util.KDTree; import fiji.util.NNearestNeighborSearch; import fiji.util.node.Leaf; import java.util.ArrayList; import mpicbg.models.Point; import mpicbg.pointdescriptor.ModelPointDescriptor; import mpicbg.pointdescriptor.exception.NoSuitablePointsException; import mpicbg.pointdescriptor.matcher.Matcher; import mpicbg.pointdescriptor.matcher.SimpleMatcher; import mpicbg.pointdescriptor.model.TranslationInvariantModel; import mpicbg.pointdescriptor.model.TranslationInvariantRigidModel3D; import mpicbg.pointdescriptor.similarity.SimilarityMeasure; import mpicbg.pointdescriptor.similarity.SquareDistance; import mpicbg.spim.mpicbg.PointMatchGeneric; import mpicbg.spim.registration.detection.DetectionView; public class ModelBased3d<T extends DetectionView<?,T>> implements CorrespondenceExtraction<T> { final Matcher matcher; final TranslationInvariantModel<?> model; public ModelBased3d( final TranslationInvariantModel<?> model, final Matcher matcher ) { this.matcher = matcher; this.model = model; } public ModelBased3d( final TranslationInvariantModel<?> model ) { this( model, new SimpleMatcher( 3 ) ); } public ModelBased3d( final Matcher matcher ) { this ( new TranslationInvariantRigidModel3D(), matcher ); } public ModelBased3d() { this( new SimpleMatcher( 3 ) ); } @Override public ArrayList<PointMatchGeneric<T>> extractCorrespondenceCandidates( final ArrayList< T > nodeListA, final ArrayList< T > nodeListB, final double differenceThreshold, final double ratioOfDistance, final boolean useAssociatedBeads) { /* create KDTrees */ final KDTree< T > treeA = new KDTree< T >( nodeListA ); final KDTree< T > treeB = new KDTree< T >( nodeListB ); /* extract point descriptors */ final int numNeighbors = matcher.getRequiredNumNeighbors(); //final TranslationInvariantModel<?> model = new TranslationInvariantRigidModel3D(); final SimilarityMeasure similarityMeasure = new SquareDistance(); final ArrayList< ModelPointDescriptor< T > > descriptors1 = createModelPointDescriptors( treeA, nodeListA, numNeighbors, model, matcher, similarityMeasure ); final ArrayList< ModelPointDescriptor< T > > descriptors2 = createModelPointDescriptors( treeB, nodeListB, numNeighbors, model, matcher, similarityMeasure ); // store the candidates for corresponding beads final ArrayList<PointMatchGeneric<T>> correspondences = new ArrayList<PointMatchGeneric<T>>(); /* compute matching */ for ( final ModelPointDescriptor< T > descriptorA : descriptors1 ) { double bestDifference = Double.MAX_VALUE; double secondBestDifference = Double.MAX_VALUE; ModelPointDescriptor< T > bestMatch = null; ModelPointDescriptor< T > secondBestMatch = null; for ( final ModelPointDescriptor< T > descriptorB : descriptors2 ) { final double difference = descriptorA.descriptorDistance( descriptorB ); if ( difference < secondBestDifference ) { secondBestDifference = difference; secondBestMatch = descriptorB; if ( secondBestDifference < bestDifference ) { double tmpDiff = secondBestDifference; ModelPointDescriptor< T > tmpMatch = secondBestMatch; secondBestDifference = bestDifference; secondBestMatch = bestMatch; bestDifference = tmpDiff; bestMatch = tmpMatch; } } } if ( bestDifference < differenceThreshold && bestDifference * ratioOfDistance <= secondBestDifference ) { final T detectionA = descriptorA.getBasisPoint(); final T detectionB = bestMatch.getBasisPoint(); detectionA.addPointDescriptorCorrespondence( detectionB, 1 ); detectionB.addPointDescriptorCorrespondence( detectionA, 1 ); correspondences.add( new PointMatchGeneric<T>( detectionA, detectionB, 1 ) ); } } return correspondences; } public static <P extends Point & Leaf<P>> ArrayList< ModelPointDescriptor< P > > createModelPointDescriptors( final KDTree< P > tree, final ArrayList< P > basisPoints, final int numNeighbors, final TranslationInvariantModel<?> model, final Matcher matcher, final SimilarityMeasure similarityMeasure ) { final NNearestNeighborSearch< P > nnsearch = new NNearestNeighborSearch< P >( tree ); final ArrayList< ModelPointDescriptor< P > > descriptors = new ArrayList< ModelPointDescriptor< P > > ( ); for ( final P point : basisPoints ) { final ArrayList< P > neighbors = new ArrayList< P >(); final P neighborList[] = nnsearch.findNNearestNeighbors( point, numNeighbors + 1 ); // the first hit is always the point itself for ( int n = 1; n < neighborList.length; ++n ) neighbors.add( neighborList[ n ] ); try { descriptors.add( new ModelPointDescriptor<P>( point, neighbors, model, similarityMeasure, matcher ) ); } catch ( NoSuitablePointsException e ) { e.printStackTrace(); } } return descriptors; } }