/*- * #%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.interestpointregistration.geometrichashing; import fiji.util.KDTree; import fiji.util.NNearestNeighborSearch; import fiji.util.node.Leaf; import java.util.ArrayList; import mpicbg.models.Point; import mpicbg.pointdescriptor.LocalCoordinateSystemPointDescriptor; import mpicbg.pointdescriptor.exception.NoSuitablePointsException; import mpicbg.spim.mpicbg.PointMatchGeneric; import spim.process.interestpointregistration.Detection; /** * Class that actually computes the geometric hashing * * @author Stephan Preibisch (stephan.preibisch@gmx.de) * */ public class GeometricHasher { public ArrayList< PointMatchGeneric< Detection > > extractCorrespondenceCandidates( final ArrayList< Detection > nodeListA, final ArrayList< Detection > nodeListB, double differenceThreshold, double ratioOfDistance, final boolean useAssociatedBeads ) { final int numNeighbors = 3; final KDTree< Detection > tree1 = new KDTree< Detection >( nodeListA ); final KDTree< Detection > tree2 = new KDTree< Detection >( nodeListB ); final ArrayList< LocalCoordinateSystemPointDescriptor< Detection > > descriptors1 = createLocalCoordinateSystemPointDescriptors( tree1, nodeListA, numNeighbors, false ); final ArrayList< LocalCoordinateSystemPointDescriptor< Detection > > descriptors2 = createLocalCoordinateSystemPointDescriptors( tree2, nodeListB, numNeighbors, false ); // create lookup tree for descriptors2 final KDTree< LocalCoordinateSystemPointDescriptor< Detection > > lookUpTree2 = new KDTree< LocalCoordinateSystemPointDescriptor< Detection > >( descriptors2 ); final NNearestNeighborSearch< LocalCoordinateSystemPointDescriptor< Detection > > nnsearch = new NNearestNeighborSearch< LocalCoordinateSystemPointDescriptor< Detection > >( lookUpTree2 ); // store the candidates for corresponding beads final ArrayList<PointMatchGeneric< Detection >> correspondences = new ArrayList<PointMatchGeneric<Detection>>(); /* compute matching */ computeMatching( descriptors1, nnsearch, correspondences, differenceThreshold, ratioOfDistance ); return correspondences; } protected void computeMatching( final ArrayList< LocalCoordinateSystemPointDescriptor< Detection > > descriptors1, final NNearestNeighborSearch< LocalCoordinateSystemPointDescriptor< Detection > > nnsearch2, final ArrayList<PointMatchGeneric<Detection>> correspondences, final double differenceThreshold, final double ratioOfDistance ) { //System.out.println( "BeadA" + "\t" + "BeadB1" + "\t" + "BeadB2" + "\t" + "Diff1" + "\t" + "Diff2" ); for ( final LocalCoordinateSystemPointDescriptor< Detection > descriptorA : descriptors1 ) { final LocalCoordinateSystemPointDescriptor< Detection > matches[] = nnsearch2.findNNearestNeighbors( descriptorA, 2 ); double best = descriptorA.descriptorDistance( matches[ 0 ] ); double secondBest = descriptorA.descriptorDistance( matches[ 1 ] ); if ( best < differenceThreshold && best * ratioOfDistance <= secondBest ) { final Detection detectionA = descriptorA.getBasisPoint(); final Detection detectionB = matches[ 0 ].getBasisPoint(); //System.out.println( beadA.getID() + "\t" + matches[ 0 ].getBasisPoint().getID() + "\t" + matches[ 1 ].getBasisPoint().getID() + "\t" + best + "\t" + secondBest ); //detectionA.addPointDescriptorCorrespondence( detectionB, 1 ); //detectionB.addPointDescriptorCorrespondence( detectionA, 1 ); correspondences.add( new PointMatchGeneric<Detection>( detectionA, detectionB, 1 ) ); } } //System.exit( 0 ); } public static <P extends Point & Leaf<P>> ArrayList< LocalCoordinateSystemPointDescriptor< P > > createLocalCoordinateSystemPointDescriptors( final KDTree< P > tree, final ArrayList< P > basisPoints, final int numNeighbors, final boolean normalize ) { final NNearestNeighborSearch< P > nnsearch = new NNearestNeighborSearch< P >( tree ); final ArrayList< LocalCoordinateSystemPointDescriptor< P > > descriptors = new ArrayList< LocalCoordinateSystemPointDescriptor< 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 LocalCoordinateSystemPointDescriptor<P>( point, neighbors, normalize ) ); } catch ( NoSuitablePointsException e ) { e.printStackTrace(); } } return descriptors; } }