Example Feature Selector Limit
From BoofCV
Jump to navigationJump to search
- Example limit select n.png
Select N most intense features
- Example limit uniform.png
Forces features to be selected across the image using bining
- Example limit random.png
Randomly selects N features
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);
}
}