/* * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package boofcv.gui.feature; import boofcv.struct.feature.AssociatedIndex; import boofcv.struct.geo.AssociatedPair; import georegression.struct.point.Point2D_F64; import org.ddogleg.struct.FastQueue; import java.awt.*; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * Shows which two features are associated with each other. An individual feature * can be shown alone by clicking on it. * * @author Peter Abeles */ public class AssociationPanel extends CompareTwoImagePanel implements MouseListener { // which features are associated with each other private int assocLeft[],assocRight[]; // color of each points. Randomly select at runtime Color colors[]; public AssociationPanel(int borderSize ) { super(borderSize,true); } public synchronized void setAssociation( List<Point2D_F64> leftPts , List<Point2D_F64> rightPts, FastQueue<AssociatedIndex> matches ) { List<Point2D_F64> allLeft = new ArrayList<>(); List<Point2D_F64> allRight = new ArrayList<>(); assocLeft = new int[ matches.size() ]; assocRight = new int[ matches.size() ]; for (int i = 0; i < matches.size(); i++) { AssociatedIndex a = matches.get(i); allLeft.add( leftPts.get(a.src)); allRight.add( rightPts.get(a.dst)); assocLeft[i] = i; assocRight[i] = i; } setLocation(allLeft,allRight); // assocLeft = new int[ leftPts.size() ]; // assocRight = new int[ rightPts.size() ]; // // for( int i = 0; i < assocLeft.length; i++ ) // assocLeft[i] = -1; // for( int i = 0; i < assocRight.length; i++ ) // assocRight[i] = -1; // // for( int i = 0; i < matches.size; i++ ) { // AssociatedIndex a = matches.get(i); // assocLeft[a.src] = a.dst; // assocRight[a.dst] = a.src; // } Random rand = new Random(234); colors = new Color[ leftPts.size() ]; for( int i = 0; i < colors.length; i++ ) { colors[i] = new Color(rand.nextInt() | 0xFF000000 ); } } public synchronized void setAssociation( List<AssociatedPair> matches ) { List<Point2D_F64> leftPts = new ArrayList<>(); List<Point2D_F64> rightPts = new ArrayList<>(); for( AssociatedPair p : matches ) { leftPts.add(p.p1); rightPts.add(p.p2); } setLocation(leftPts,rightPts); assocLeft = new int[ leftPts.size() ]; assocRight = new int[ rightPts.size() ]; for( int i = 0; i < assocLeft.length; i++ ) { assocLeft[i] = i; assocRight[i] = i; } Random rand = new Random(234); colors = new Color[ leftPts.size() ]; for( int i = 0; i < colors.length; i++ ) { colors[i] = new Color(rand.nextInt() | 0xFF000000 ); } } public synchronized void setAssociation( List<Point2D_F64> leftPts , List<Point2D_F64> rightPts ) { setLocation(leftPts,rightPts); assocLeft = new int[ leftPts.size() ]; assocRight = new int[ rightPts.size() ]; for( int i = 0; i < assocLeft.length; i++ ) { assocLeft[i] = i; assocRight[i] = i; } Random rand = new Random(234); colors = new Color[ leftPts.size() ]; for( int i = 0; i < colors.length; i++ ) { colors[i] = new Color(rand.nextInt() | 0xFF000000 ); } } @Override protected void drawFeatures(Graphics2D g2 , double scaleLeft, int leftX, int leftY, double scaleRight, int rightX, int rightY) { if( selected.isEmpty() ) drawAllFeatures(g2, scaleLeft,scaleRight,rightX); else { for( int selectedIndex : selected ) { // draw just an individual feature pair Point2D_F64 l,r; Color color; if( selectedIsLeft ) { l = leftPts.get(selectedIndex); if( assocLeft[selectedIndex] < 0 ) { r = null; color = null; } else { r = rightPts.get(assocLeft[selectedIndex]); color = colors[selectedIndex]; } } else { r = rightPts.get(selectedIndex); if( assocRight[selectedIndex] < 0 ) { l = null; color = null; } else { l = leftPts.get(assocRight[selectedIndex]); color = colors[assocRight[selectedIndex]]; } } if( color == null ) // clicking on something with no association is annoying drawAllFeatures(g2, scaleLeft,scaleRight,rightX); else drawAssociation(g2, scaleLeft,scaleRight,rightX, l, r, color); } } } private void drawAllFeatures(Graphics2D g2, double scaleLeft , double scaleRight , int rightX) { if( assocLeft == null || rightPts == null || leftPts == null ) return; for( int i = 0; i < assocLeft.length; i++ ) { if( assocLeft[i] == -1 ) continue; Point2D_F64 l = leftPts.get(i); Point2D_F64 r = rightPts.get(assocLeft[i]); Color color = colors[i]; drawAssociation(g2, scaleLeft,scaleRight,rightX, l, r, color); } } private void drawAssociation(Graphics2D g2, double scaleLeft , double scaleRight , int rightX, Point2D_F64 l, Point2D_F64 r, Color color) { if( r == null ) { int x1 = (int)(scaleLeft*l.x); int y1 = (int)(scaleLeft*l.y); VisualizeFeatures.drawPoint(g2,x1,y1,Color.RED); } else if( l == null ) { int x2 = (int)(scaleRight*r.x) + rightX; int y2 = (int)(scaleRight*r.y); VisualizeFeatures.drawPoint(g2,x2,y2,Color.RED); } else { int x1 = (int)(scaleLeft*l.x); int y1 = (int)(scaleLeft*l.y); VisualizeFeatures.drawPoint(g2,x1,y1,color); int x2 = (int)(scaleRight*r.x) + rightX; int y2 = (int)(scaleRight*r.y); VisualizeFeatures.drawPoint(g2,x2,y2,color); g2.setColor(color); g2.drawLine(x1,y1,x2,y2); } } @Override protected boolean isValidPoint(int index) { if( selectedIsLeft ) return assocLeft[index] >= 0; else return assocRight[index] >= 0; } }