Difference between revisions of "Example Feature Selector Limit"

From BoofCV
Jump to navigationJump to search
(Created page with "<center> <center> <gallery heights=220 widths=220 > File:Example_limit_select_n.png|Select N most intense features File:Example_limit_uniform.png|Forces features to be selecte...")
 
m
Line 2: Line 2:
<center>
<center>
<gallery heights=220 widths=220 >
<gallery heights=220 widths=220 >
File:Standard_boat.jpg|Input
File:Example_limit_select_n.png|Select N most intense features
File:Example_limit_select_n.png|Select N most intense features
File:Example_limit_uniform.png|Forces features to be selected across the image using bining
File:Example_limit_uniform.png|Forces features to be selected across the image using bining

Revision as of 14:53, 2 September 2022

When detecting interest points and other point features inside an image there's often the need to limit how many you consider. This can be a way to limit the amount of computational resources required. BoofCV provides the NonMaxLimiter as an abstract way to do just that and several different implementations. For some applications you might wish to only select the most intense features, others you might need to select features across the entire image to ensure numeric stability, or maybe random is good enough.

Example File: ExampleCalibrateMonocular.java

Calibration Tutorial: Wikipage

Concepts:

  • Corner detectors
  • Interest point detectors

Related Examples:

Example Code

/**
 * Visualization of feature Select Limit. After non-maximum suppression, select limit decides which detected
 * features should be used when the requested number of features is exceeded by the number of detected features.
 * Typically, you either want the most intense features or you want to ensure that features are selected
 * throughout the image.
 *
 * @author Peter Abeles
 */
public class ExampleFeatureLimit {
	// Radius for non-maximum suppression
	public static final int NON_MAX_RADIUS = 5;

	// Maximum number of features it will return
	public static final int MAX_FEATURES = 200;

	public static BufferedImage renderLimit( GrayF32 intensity, SelectLimitTypes type ) {
		// Configure how it will select features inside the intensity image
		var limit = new ConfigSelectLimit(type, 0xBEEF);
		NonMaxLimiter nonmax = FactoryFeatureExtractor.nonmaxLimiter(new ConfigExtract(NON_MAX_RADIUS, 0), limit, MAX_FEATURES);

		// Detect the features
		nonmax.process(intensity);
		FastAccess<LocalExtreme> features = nonmax.getFeatures();

		// Visualize the intensity image
		var output = new BufferedImage(intensity.width, intensity.height, BufferedImage.TYPE_INT_RGB);
		VisualizeImageData.colorizeSign(intensity, output, -1);

		// render each selected maximum with a circle
		Graphics2D g2 = output.createGraphics();
		g2.setColor(Color.blue);
		for (int i = 0; i < features.size(); i++) {
			LocalExtreme c = features.get(i);
			VisualizeFeatures.drawCircle(g2, c.location.x, c.location.y, NON_MAX_RADIUS);
		}
		return output;
	}

	public static void main( String[] args ) {
		BufferedImage buffered = UtilImageIO.loadImageNotNull(UtilIO.pathExample("standard/boat.jpg"));

		GrayF32 input = ConvertBufferedImage.convertFrom(buffered, (GrayF32)null);

		// Compute the image gradient
		GrayF32 derivX = input.createSameShape();
		GrayF32 derivY = input.createSameShape();

		GImageDerivativeOps.gradient(DerivativeType.SOBEL, input, derivX, derivY, BorderType.EXTENDED);

		// From the gradient compute intensity of shi-tomasi features
		GeneralFeatureIntensity<GrayF32, GrayF32> featureIntensity =
				FactoryIntensityPoint.shiTomasi(3, false, GrayF32.class);

		featureIntensity.process(input, derivX, derivY, null, null, null);
		GrayF32 intensity = featureIntensity.getIntensity();

		var panel = new ListDisplayPanel();
		panel.addImage(buffered, "Input Image");

		// Detect maximums with different settings and visualize the results
		for (var type : SelectLimitTypes.values()) {
			panel.addImage(renderLimit(intensity, type), type.name());
		}

		ShowImages.showWindow(panel, "Non-Max with Limiter", true);
	}
}