Difference between revisions of "Example SURF Feature"
From BoofCV
Jump to navigationJump to searchm |
m |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Speeded Up Robust Feature (SURF) is a region descriptor and interest point detector. Two different ways of using SURF are demonstrated in this example. The easy way uses a high level interface that is easy to work with, but sacrifices flexibility. The harder way directly creates the SURF classes, is more complex, and requires a better understanding of how the code works. | Speeded Up Robust Feature (SURF) is a region descriptor and interest point detector. Two different ways of using SURF are demonstrated in this example. The easy way uses a high level interface that is easy to work with, but sacrifices flexibility. The harder way directly creates the SURF classes, is more complex, and requires a better understanding of how the code works. | ||
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0. | Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/features/ExampleFeatureSurf.java ExampleFeatureSurf.java] | ||
Concepts: | Concepts: | ||
Line 17: | Line 17: | ||
*/ | */ | ||
public class ExampleFeatureSurf { | public class ExampleFeatureSurf { | ||
/** | /** | ||
* Use generalized interfaces for working with SURF. | * Use generalized interfaces for working with SURF. This removes much of the drudgery, but also reduces flexibility | ||
* and slightly increases memory and computational requirements. | * and slightly increases memory and computational requirements. | ||
* | * | ||
Line 26: | Line 25: | ||
public static void easy( GrayF32 image ) { | public static void easy( GrayF32 image ) { | ||
// create the detector and descriptors | // create the detector and descriptors | ||
DetectDescribePoint<GrayF32, | ConfigFastHessian configDetector = new ConfigFastHessian(); | ||
surfStable( | configDetector.extract = new ConfigExtract(2, 0, 5, true); | ||
configDetector.maxFeaturesPerScale = 200; | |||
configDetector.initialSampleStep = 2; | |||
DetectDescribePoint<GrayF32,TupleDesc_F64> surf = FactoryDetectDescribe. | |||
surfStable(configDetector, null, null,GrayF32.class); | |||
// specify the image to process | // specify the image to process | ||
Line 33: | Line 37: | ||
System.out.println("Found Features: "+surf.getNumberOfFeatures()); | System.out.println("Found Features: "+surf.getNumberOfFeatures()); | ||
System.out.println("First descriptor's first value: "+surf.getDescription(0). | System.out.println("First descriptor's first value: "+surf.getDescription(0).data[0]); | ||
} | } | ||
/** | /** | ||
* Configured exactly the same as the easy example above, but require a lot more code and a more in depth | * Configured exactly the same as the easy example above, but require a lot more code and a more in depth | ||
* understanding of how SURF works and is configured. | * understanding of how SURF works and is configured. Each sub-problem which composes "SURF" is now explicitly | ||
* created and configured independently. This allows an advance user to tune it for a specific problem. | |||
* | * | ||
* | |||
* @param image Input image type. DOES NOT NEED TO BE GrayF32, GrayU8 works too | * @param image Input image type. DOES NOT NEED TO BE GrayF32, GrayU8 works too | ||
*/ | */ | ||
Line 49: | Line 52: | ||
// define the feature detection algorithm | // define the feature detection algorithm | ||
ConfigFastHessian config = new ConfigFastHessian(); | |||
config.extract = new ConfigExtract(2, 0, 5, true); | |||
FastHessianFeatureDetector<II> detector = | config.maxFeaturesPerScale = 200; | ||
config.initialSampleStep = 2; | |||
FastHessianFeatureDetector<II> detector = FactoryInterestPointAlgs.fastHessian(config); | |||
// estimate orientation | // estimate orientation | ||
OrientationIntegral<II> orientation = | OrientationIntegral<II> orientation = FactoryOrientationAlgs.sliding_ii(null, integralType); | ||
DescribePointSurf<II> descriptor = | DescribePointSurf<II> descriptor = FactoryDescribeAlgs.surfStability(null,integralType); | ||
// compute the integral image of 'image' | // compute the integral image of 'image' | ||
Line 70: | Line 73: | ||
descriptor.setImage(integral); | descriptor.setImage(integral); | ||
List<ScalePoint> points = detector. | List<ScalePoint> points = detector.getFoundFeatures(); | ||
List< | List<TupleDesc_F64> descriptions = new ArrayList<>(); | ||
for( ScalePoint p : points ) { | for( ScalePoint p : points ) { | ||
// estimate orientation | // estimate orientation | ||
orientation.setObjectRadius( p.scale*BoofDefaults.SURF_SCALE_TO_RADIUS); | orientation.setObjectRadius( p.scale*BoofDefaults.SURF_SCALE_TO_RADIUS); | ||
double angle = orientation.compute(p.x,p.y); | double angle = orientation.compute(p.pixel.x,p.pixel.y); | ||
// extract the SURF description for this region | // extract the SURF description for this region | ||
TupleDesc_F64 desc = descriptor.createDescription(); | |||
descriptor.describe(p.x,p.y,angle,p.scale,desc); | descriptor.describe(p.pixel.x,p.pixel.y,angle,p.scale, true, desc); | ||
// save everything for processing later on | // save everything for processing later on | ||
Line 88: | Line 91: | ||
System.out.println("Found Features: "+points.size()); | System.out.println("Found Features: "+points.size()); | ||
System.out.println("First descriptor's first value: "+descriptions.get(0). | System.out.println("First descriptor's first value: "+descriptions.get(0).data[0]); | ||
} | } | ||
public static void main( String | public static void main( String[] args ) { | ||
// Need to turn off concurrency since the order in which feature are returned | // Need to turn off concurrency since the order in which feature are returned | ||
// is not | // is not deterministic if turned on | ||
BoofConcurrency.USE_CONCURRENT = false; | BoofConcurrency.USE_CONCURRENT = false; | ||
Line 104: | Line 106: | ||
System.out.println("Done!"); | System.out.println("Done!"); | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 12:59, 17 January 2022
Speeded Up Robust Feature (SURF) is a region descriptor and interest point detector. Two different ways of using SURF are demonstrated in this example. The easy way uses a high level interface that is easy to work with, but sacrifices flexibility. The harder way directly creates the SURF classes, is more complex, and requires a better understanding of how the code works.
Example File: ExampleFeatureSurf.java
Concepts:
- SURF
- Region Descriptor
- Interest Point
Example Code
/**
* Example of how to use SURF detector and descriptors in BoofCV.
*
* @author Peter Abeles
*/
public class ExampleFeatureSurf {
/**
* Use generalized interfaces for working with SURF. This removes much of the drudgery, but also reduces flexibility
* and slightly increases memory and computational requirements.
*
* @param image Input image type. DOES NOT NEED TO BE GrayF32, GrayU8 works too
*/
public static void easy( GrayF32 image ) {
// create the detector and descriptors
ConfigFastHessian configDetector = new ConfigFastHessian();
configDetector.extract = new ConfigExtract(2, 0, 5, true);
configDetector.maxFeaturesPerScale = 200;
configDetector.initialSampleStep = 2;
DetectDescribePoint<GrayF32,TupleDesc_F64> surf = FactoryDetectDescribe.
surfStable(configDetector, null, null,GrayF32.class);
// specify the image to process
surf.detect(image);
System.out.println("Found Features: "+surf.getNumberOfFeatures());
System.out.println("First descriptor's first value: "+surf.getDescription(0).data[0]);
}
/**
* Configured exactly the same as the easy example above, but require a lot more code and a more in depth
* understanding of how SURF works and is configured. Each sub-problem which composes "SURF" is now explicitly
* created and configured independently. This allows an advance user to tune it for a specific problem.
*
* @param image Input image type. DOES NOT NEED TO BE GrayF32, GrayU8 works too
*/
public static <II extends ImageGray<II>> void harder(GrayF32 image ) {
// SURF works off of integral images
Class<II> integralType = GIntegralImageOps.getIntegralType(GrayF32.class);
// define the feature detection algorithm
ConfigFastHessian config = new ConfigFastHessian();
config.extract = new ConfigExtract(2, 0, 5, true);
config.maxFeaturesPerScale = 200;
config.initialSampleStep = 2;
FastHessianFeatureDetector<II> detector = FactoryInterestPointAlgs.fastHessian(config);
// estimate orientation
OrientationIntegral<II> orientation = FactoryOrientationAlgs.sliding_ii(null, integralType);
DescribePointSurf<II> descriptor = FactoryDescribeAlgs.surfStability(null,integralType);
// compute the integral image of 'image'
II integral = GeneralizedImageOps.createSingleBand(integralType,image.width,image.height);
GIntegralImageOps.transform(image, integral);
// detect fast hessian features
detector.detect(integral);
// tell algorithms which image to process
orientation.setImage(integral);
descriptor.setImage(integral);
List<ScalePoint> points = detector.getFoundFeatures();
List<TupleDesc_F64> descriptions = new ArrayList<>();
for( ScalePoint p : points ) {
// estimate orientation
orientation.setObjectRadius( p.scale*BoofDefaults.SURF_SCALE_TO_RADIUS);
double angle = orientation.compute(p.pixel.x,p.pixel.y);
// extract the SURF description for this region
TupleDesc_F64 desc = descriptor.createDescription();
descriptor.describe(p.pixel.x,p.pixel.y,angle,p.scale, true, desc);
// save everything for processing later on
descriptions.add(desc);
}
System.out.println("Found Features: "+points.size());
System.out.println("First descriptor's first value: "+descriptions.get(0).data[0]);
}
public static void main( String[] args ) {
// Need to turn off concurrency since the order in which feature are returned
// is not deterministic if turned on
BoofConcurrency.USE_CONCURRENT = false;
GrayF32 image = UtilImageIO.loadImage(UtilIO.pathExample("particles01.jpg"), GrayF32.class);
// run each example
ExampleFeatureSurf.easy(image);
ExampleFeatureSurf.harder(image);
System.out.println("Done!");
}
}