boofcv.gui.feature.AssociationPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boofcv-swing Show documentation
Show all versions of boofcv-swing Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* Copyright (c) 2021, 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.FastAccess;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
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
*/
@SuppressWarnings({"NullAway.Init"})
public class AssociationPanel extends CompareTwoImagePanel implements MouseListener {
// lock for all the data structures below
final Object lock = new Object();
// 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 void setAssociation( List leftPts, List rightPts,
FastAccess matches ) {
synchronized (lock) {
List allLeft = new ArrayList<>();
List 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);
Random rand = new Random(234);
colors = new Color[matches.size()];
for (int i = 0; i < matches.size(); i++) {
colors[i] = new Color(rand.nextInt() | 0xFF000000);
}
}
}
public void setAssociation( List matches ) {
synchronized (lock) {
List leftPts = new ArrayList<>();
List 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[matches.size()];
for (int i = 0; i < colors.length; i++) {
colors[i] = new Color(rand.nextInt() | 0xFF000000);
}
}
}
public void setAssociation( List leftPts, List rightPts ) {
synchronized (lock) {
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 ) {
synchronized (lock) {
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,
@Nullable Point2D_F64 l, @Nullable Point2D_F64 r, Color color ) {
if (r == null) {
Objects.requireNonNull(l);
int x1 = (int)(scaleLeft*l.x);
int y1 = (int)(scaleLeft*l.y);
VisualizeFeatures.drawPoint(g2, x1, y1, Color.RED);
} else if (l == null) {
Objects.requireNonNull(r);
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;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy