All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.gui.feature.AssociationPanel Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

There is a newer version: 1.1.7
Show newest version
/*
 * 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