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

boofcv.gui.controls.ControlPanelDetDescAssocBase 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) 2022, 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.controls;

import boofcv.abst.feature.associate.AssociateDescription;
import boofcv.abst.feature.associate.AssociateDescription2D;
import boofcv.abst.feature.describe.DescribePointRadiusAngle;
import boofcv.abst.feature.describe.DescriptorInfo;
import boofcv.abst.feature.detdesc.DetectDescribePoint;
import boofcv.abst.feature.detect.interest.InterestPointDetector;
import boofcv.factory.feature.associate.ConfigAssociate;
import boofcv.factory.feature.associate.FactoryAssociation;
import boofcv.factory.feature.describe.ConfigDescribeRegion;
import boofcv.factory.feature.describe.FactoryDescribePointRadiusAngle;
import boofcv.factory.feature.detdesc.ConfigDetectDescribe;
import boofcv.factory.feature.detdesc.FactoryDetectDescribe;
import boofcv.factory.feature.detect.interest.ConfigDetectInterestPoint;
import boofcv.factory.feature.detect.interest.FactoryInterestPoint;
import boofcv.gui.StandardAlgConfigPanel;
import boofcv.gui.feature.*;
import boofcv.struct.feature.TupleDesc;
import boofcv.struct.feature.TupleDesc_F64;
import boofcv.struct.image.ImageBase;
import boofcv.struct.image.ImageGray;
import boofcv.struct.image.ImageType;

import javax.swing.*;

/**
 * Contains controls for all the usual detectors, descriptors, and associations. Mostly contains boiler plate
 * and leaves the final visualization step to the implementing class.
 *
 * @author Peter Abeles
 */
@SuppressWarnings({"NullAway.Init"})
public abstract class ControlPanelDetDescAssocBase extends StandardAlgConfigPanel {
	protected JComboBox comboDetect;
	protected JComboBox comboDescribe;
	protected JComboBox comboAssociate;

	// Configurations. Modify these before calling initializeControlsGUI
	public ConfigDetectDescribe configDetDesc = new ConfigDetectDescribe();
	public ConfigAssociate configAssociate = new ConfigAssociate();

	// Controls for different detectors / descriptors
	public ControlPanelSiftDetector controlDetectSift;
	public ControlPanelFastHessian controlDetectFastHessian;
	public ControlPanelPointDetector controlDetectPoint;
	public ControlPanelSurfDescribe.Speed controlDescSurfFast;
	public ControlPanelSurfDescribe.Stability controlDescSurfStable;
	public ControlPanelDescribeSift controlDescSift;
	public ControlPanelDescribeBrief controlDescBrief;
	public ControlPanelDescribeTemplate controlDescTemplate;
	public ControlPanelAssociateGreedy controlAssocGreedy;
	public ControlPanelAssociateNearestNeighbor controlAssocNN;
	public JConfigLength controlAssocMaxDistance;
	public boolean associateWithPixels = false;

	// Control panel for associating with 2d pixels
	public StandardAlgConfigPanel panelAssociate2D = new StandardAlgConfigPanel();

	protected ControlPanelDetDescAssocBase() {}

	protected ControlPanelDetDescAssocBase( ConfigDetectDescribe configDetDesc,
											ConfigAssociate configAssociate ) {
		this.configDetDesc = configDetDesc;
		this.configAssociate = configAssociate;
	}

	public void initializeControlsGUI() {
		comboDetect = combo(configDetDesc.typeDetector.ordinal(), (Object[])ConfigDetectInterestPoint.Type.values());
		comboDescribe = combo(configDetDesc.typeDescribe.ordinal(), (Object[])ConfigDescribeRegion.Type.values());
		if (associateWithPixels) {
			comboAssociate = combo(configAssociate.type.ordinal(), ConfigAssociate.AssociationType.GREEDY);
		} else {
			comboAssociate = combo(configAssociate.type.ordinal(), (Object[])ConfigAssociate.AssociationType.values());
		}

		controlDetectSift = new ControlPanelSiftDetector(configDetDesc.scaleSpaceSift, configDetDesc.detectSift, this::handleControlsUpdated);
		controlDetectFastHessian = new ControlPanelFastHessian(configDetDesc.detectFastHessian, this::handleControlsUpdated);
		controlDetectPoint = new ControlPanelPointDetector(configDetDesc.detectPoint, this::handleControlsUpdated);
		controlDescSurfFast = new ControlPanelSurfDescribe.Speed(configDetDesc.describeSurfFast, this::handleControlsUpdated);
		controlDescSurfStable = new ControlPanelSurfDescribe.Stability(configDetDesc.describeSurfStability, this::handleControlsUpdated);
		controlDescSift = new ControlPanelDescribeSift(configDetDesc.describeSift, this::handleControlsUpdated);
		controlDescBrief = new ControlPanelDescribeBrief(configDetDesc.describeBrief, this::handleControlsUpdated);
		controlDescTemplate = new ControlPanelDescribeTemplate(configDetDesc.describeTemplate, this::handleControlsUpdated);
		controlAssocGreedy = new ControlPanelAssociateGreedy(configAssociate.greedy, this::handleControlsUpdated);
		controlAssocNN = new ControlPanelAssociateNearestNeighbor(configAssociate.nearestNeighbor, this::handleControlsUpdated);
		controlAssocMaxDistance = configLength(configAssociate.maximumDistancePixels, 0, 2000, this::handleControlsUpdated);

		panelAssociate2D.addLabeled(controlAssocMaxDistance, "Max Dist", "Maximum distance two features can be to be associated");
		panelAssociate2D.add(controlAssocGreedy);

		controlDetectSift.setBorder(BorderFactory.createEmptyBorder());
		controlDetectFastHessian.setBorder(BorderFactory.createEmptyBorder());
		controlDetectPoint.setBorder(BorderFactory.createEmptyBorder());
		controlDescSurfFast.setBorder(BorderFactory.createEmptyBorder());
		controlDescSurfStable.setBorder(BorderFactory.createEmptyBorder());
		controlDescSift.setBorder(BorderFactory.createEmptyBorder());
		controlDescBrief.setBorder(BorderFactory.createEmptyBorder());
		controlDescTemplate.setBorder(BorderFactory.createEmptyBorder());
		controlAssocGreedy.setBorder(BorderFactory.createEmptyBorder());
		controlAssocNN.setBorder(BorderFactory.createEmptyBorder());
		panelAssociate2D.setBorder(BorderFactory.createEmptyBorder());
	}

	/**
	 * Called when the user modifies a setting in one of the controls. Should be overloaded by
	 * an extending class.
	 */
	protected abstract void handleControlsUpdated();

	public JPanel getDetectorPanel() {
		return switch (configDetDesc.typeDetector) {
			case FAST_HESSIAN -> controlDetectFastHessian;
			case SIFT -> controlDetectSift;
			case POINT -> controlDetectPoint;
			default -> throw new IllegalArgumentException("Unknown");
		};
	}

	public JPanel getDescriptorPanel() {
		return switch (configDetDesc.typeDescribe) {
			case SURF_FAST, SURF_COLOR_FAST -> controlDescSurfFast;
			case SURF_STABLE, SURF_COLOR_STABLE -> controlDescSurfStable;
			case SIFT -> controlDescSift;
			case BRIEF -> controlDescBrief;
			case TEMPLATE -> controlDescTemplate;
			default -> throw new IllegalArgumentException("Unknown: " + configDetDesc.typeDescribe);
		};
	}

	public JPanel getAssociatePanel() {
		if (associateWithPixels) {
			return panelAssociate2D;
		} else {
			return switch (configAssociate.type) {
				case GREEDY -> controlAssocGreedy;
				case KD_TREE, RANDOM_FOREST -> controlAssocNN;
				default -> throw new IllegalArgumentException("Unknown");
			};
		}
	}

	/**
	 * Creates an implementation of {@link DetectDescribePoint}. if possible a specialized implementation is created
	 */
	public , D extends ImageGray>
	DetectDescribePoint createDetectDescribe( Class imageType ) {
		return FactoryDetectDescribe.generic(configDetDesc, imageType);
	}

	public , D extends ImageGray>
	InterestPointDetector createDetector( Class imageType ) {
		var c = new ConfigDetectInterestPoint();
		c.type = configDetDesc.typeDetector;
		c.fastHessian = configDetDesc.detectFastHessian;
		c.point = configDetDesc.detectPoint;
		c.scaleSpaceSift = configDetDesc.scaleSpaceSift;
		c.sift = configDetDesc.detectSift;

		return FactoryInterestPoint.generic(c, imageType, null);
	}

	public , TD extends TupleDesc>
	DescribePointRadiusAngle createDescriptor( Class imageType ) {
		return createDescriptor(ImageType.single(imageType));
	}

	public , TD extends TupleDesc>
	DescribePointRadiusAngle createDescriptor( ImageType imageType ) {
		var c = new ConfigDescribeRegion();
		c.type = configDetDesc.typeDescribe;
		c.brief = configDetDesc.describeBrief;
		c.surfFast = configDetDesc.describeSurfFast;
		c.surfStability = configDetDesc.describeSurfStability;
		c.scaleSpaceSift = configDetDesc.scaleSpaceSift;
		c.template = configDetDesc.describeTemplate;

		return FactoryDescribePointRadiusAngle.generic(c, imageType);
	}

	public AssociateDescription createAssociate( DescriptorInfo descriptor ) {

		if (configAssociate.type != ConfigAssociate.AssociationType.GREEDY) {
			// The best way to handle this situation is to make it so the user can't select this combination of options
			if (!TupleDesc_F64.class.isAssignableFrom(descriptor.getDescriptionType())) {
				JOptionPane.showMessageDialog(this, "Requires TupleDesc_F64 description type");
				// not really sure what to do here. I'll just force it to be greedy to avoid a crash
				configAssociate.type = ConfigAssociate.AssociationType.GREEDY;
			}
		}

		return FactoryAssociation.generic(configAssociate, descriptor);
	}

	public AssociateDescription2D createAssociate2( DescriptorInfo descriptor ) {

		configAssociate.maximumDistancePixels.setTo(controlAssocMaxDistance.getValue());

		if (configAssociate.type != ConfigAssociate.AssociationType.GREEDY) {
			// The best way to handle this situation is to make it so the user can't select this combination of options
			if (!TupleDesc_F64.class.isAssignableFrom(descriptor.getDescriptionType())) {
				JOptionPane.showMessageDialog(this, "Requires TupleDesc_F64 description type");
				// not really sure what to do here. I'll just force it to be greedy to avoid a crash
				configAssociate.type = ConfigAssociate.AssociationType.GREEDY;
			}
		}

		return FactoryAssociation.generic2(configAssociate, descriptor);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy