Difference between revisions of "Example Associate Interest Points"
From BoofCV
Jump to navigationJump to searchm |
m |
||
(3 intermediate revisions by the same user not shown) | |||
Line 10: | Line 10: | ||
Example Code: | Example Code: | ||
* [https://github.com/lessthanoptimal/BoofCV/ | * [https://github.com/lessthanoptimal/BoofCV/tree/v0.40/examples/src/main/java/boofcv/examples/features/ExampleAssociatePoints.java ExampleAssociatePoints.java] | ||
Concepts: | Concepts: | ||
Line 21: | Line 21: | ||
/** | /** | ||
* After interest points have been detected in two images the next step is to associate the two | * After interest points have been detected in two images the next step is to associate the two | ||
* sets of images so that the relationship can be found. | * sets of images so that the relationship can be found. This is done by computing descriptors for | ||
* each detected feature and associating them together. | * each detected feature and associating them together. In the code below abstracted interfaces are | ||
* used to allow different algorithms to be easily used. | * used to allow different algorithms to be easily used. The cost of this abstraction is that detector/descriptor | ||
* specific information is thrown away, potentially slowing down or degrading performance. | * specific information is thrown away, potentially slowing down or degrading performance. | ||
* | * | ||
* @author Peter Abeles | * @author Peter Abeles | ||
*/ | */ | ||
public class ExampleAssociatePoints<T extends ImageGray<T>, TD extends TupleDesc> { | public class ExampleAssociatePoints<T extends ImageGray<T>, TD extends TupleDesc<TD>> { | ||
// algorithm used to detect and describe interest points | // algorithm used to detect and describe interest points | ||
Line 41: | Line 41: | ||
Class<T> imageType; | Class<T> imageType; | ||
public ExampleAssociatePoints(DetectDescribePoint<T, TD> detDesc, | public ExampleAssociatePoints( DetectDescribePoint<T, TD> detDesc, | ||
AssociateDescription<TD> associate, | |||
Class<T> imageType ) { | |||
this.detDesc = detDesc; | this.detDesc = detDesc; | ||
this.associate = associate; | this.associate = associate; | ||
Line 50: | Line 50: | ||
/** | /** | ||
* Detect and associate point features in the two images. | * Detect and associate point features in the two images. Display the results. | ||
*/ | */ | ||
public void associate( BufferedImage imageA , BufferedImage imageB ) | public void associate( BufferedImage imageA, BufferedImage imageB ) { | ||
T inputA = ConvertBufferedImage.convertFromSingle(imageA, null, imageType); | T inputA = ConvertBufferedImage.convertFromSingle(imageA, null, imageType); | ||
T inputB = ConvertBufferedImage.convertFromSingle(imageB, null, imageType); | T inputB = ConvertBufferedImage.convertFromSingle(imageB, null, imageType); | ||
Line 62: | Line 61: | ||
// stores the description of detected interest points | // stores the description of detected interest points | ||
DogArray<TD> descA = UtilFeature.createArray(detDesc, 100); | |||
DogArray<TD> descB = UtilFeature.createArray(detDesc, 100); | |||
// describe each image using interest points | // describe each image using interest points | ||
describeImage(inputA,pointsA,descA); | describeImage(inputA, pointsA, descA); | ||
describeImage(inputB,pointsB,descB); | describeImage(inputB, pointsB, descB); | ||
// Associate features between the two images | // Associate features between the two images | ||
Line 76: | Line 75: | ||
// display the results | // display the results | ||
AssociationPanel panel = new AssociationPanel(20); | AssociationPanel panel = new AssociationPanel(20); | ||
panel.setAssociation(pointsA,pointsB,associate.getMatches()); | panel.setAssociation(pointsA, pointsB, associate.getMatches()); | ||
panel.setImages(imageA,imageB); | panel.setImages(imageA, imageB); | ||
ShowImages.showWindow(panel,"Associated Features",true); | ShowImages.showWindow(panel, "Associated Features", true); | ||
} | } | ||
Line 85: | Line 84: | ||
* Detects features inside the two images and computes descriptions at those points. | * Detects features inside the two images and computes descriptions at those points. | ||
*/ | */ | ||
private void describeImage(T input, List<Point2D_F64> points, | private void describeImage( T input, List<Point2D_F64> points, DogArray<TD> descs ) { | ||
detDesc.detect(input); | detDesc.detect(input); | ||
for( int i = 0; i < detDesc.getNumberOfFeatures(); i++ ) { | for (int i = 0; i < detDesc.getNumberOfFeatures(); i++) { | ||
points.add( detDesc.getLocation(i).copy() ); | points.add(detDesc.getLocation(i).copy()); | ||
descs.grow().setTo(detDesc.getDescription(i)); | descs.grow().setTo(detDesc.getDescription(i)); | ||
} | } | ||
} | } | ||
public static void main( String | public static void main( String[] args ) { | ||
Class imageType = GrayF32.class; | Class imageType = GrayF32.class; | ||
Line 102: | Line 100: | ||
// select which algorithms to use | // select which algorithms to use | ||
DetectDescribePoint detDesc = FactoryDetectDescribe. | DetectDescribePoint detDesc = FactoryDetectDescribe. | ||
surfStable(new ConfigFastHessian(1, 2, 300, 1, 9, 4, 4), null,null, imageType); | surfStable(new ConfigFastHessian(1, 2, 300, 1, 9, 4, 4), null, null, imageType); | ||
// sift(new ConfigCompleteSift(0,5,600)); | // sift(new ConfigCompleteSift(0,5,600)); | ||
ScoreAssociation scorer = FactoryAssociation.defaultScore(detDesc.getDescriptionType()); | ScoreAssociation scorer = FactoryAssociation.defaultScore(detDesc.getDescriptionType()); | ||
AssociateDescription associate = FactoryAssociation.greedy(new ConfigAssociateGreedy(true),scorer); | AssociateDescription associate = FactoryAssociation.greedy(new ConfigAssociateGreedy(true), scorer); | ||
// load and match images | // load and match images | ||
ExampleAssociatePoints app = new ExampleAssociatePoints(detDesc,associate,imageType); | ExampleAssociatePoints app = new ExampleAssociatePoints(detDesc, associate, imageType); | ||
BufferedImage imageA = UtilImageIO. | BufferedImage imageA = UtilImageIO.loadImageNotNull(UtilIO.pathExample("stitch/kayak_01.jpg")); | ||
BufferedImage imageB = UtilImageIO. | BufferedImage imageB = UtilImageIO.loadImageNotNull(UtilIO.pathExample("stitch/kayak_03.jpg")); | ||
app.associate(imageA,imageB); | app.associate(imageA, imageB); | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 12:30, 17 January 2022
Associated feature between images using example code. |
---|
A common problem for many computer vision applications is matching features observed in two or more images. Below is an example of how this can be accomplished using interest point and their descriptions. When run, you can click on the image to select individual points or drag a region to select several.
Example Code:
Concepts:
- Describe point features
- Associate descriptions
Example Code
/**
* After interest points have been detected in two images the next step is to associate the two
* sets of images so that the relationship can be found. This is done by computing descriptors for
* each detected feature and associating them together. In the code below abstracted interfaces are
* used to allow different algorithms to be easily used. The cost of this abstraction is that detector/descriptor
* specific information is thrown away, potentially slowing down or degrading performance.
*
* @author Peter Abeles
*/
public class ExampleAssociatePoints<T extends ImageGray<T>, TD extends TupleDesc<TD>> {
// algorithm used to detect and describe interest points
DetectDescribePoint<T, TD> detDesc;
// Associated descriptions together by minimizing an error metric
AssociateDescription<TD> associate;
// location of interest points
public List<Point2D_F64> pointsA;
public List<Point2D_F64> pointsB;
Class<T> imageType;
public ExampleAssociatePoints( DetectDescribePoint<T, TD> detDesc,
AssociateDescription<TD> associate,
Class<T> imageType ) {
this.detDesc = detDesc;
this.associate = associate;
this.imageType = imageType;
}
/**
* Detect and associate point features in the two images. Display the results.
*/
public void associate( BufferedImage imageA, BufferedImage imageB ) {
T inputA = ConvertBufferedImage.convertFromSingle(imageA, null, imageType);
T inputB = ConvertBufferedImage.convertFromSingle(imageB, null, imageType);
// stores the location of detected interest points
pointsA = new ArrayList<>();
pointsB = new ArrayList<>();
// stores the description of detected interest points
DogArray<TD> descA = UtilFeature.createArray(detDesc, 100);
DogArray<TD> descB = UtilFeature.createArray(detDesc, 100);
// describe each image using interest points
describeImage(inputA, pointsA, descA);
describeImage(inputB, pointsB, descB);
// Associate features between the two images
associate.setSource(descA);
associate.setDestination(descB);
associate.associate();
// display the results
AssociationPanel panel = new AssociationPanel(20);
panel.setAssociation(pointsA, pointsB, associate.getMatches());
panel.setImages(imageA, imageB);
ShowImages.showWindow(panel, "Associated Features", true);
}
/**
* Detects features inside the two images and computes descriptions at those points.
*/
private void describeImage( T input, List<Point2D_F64> points, DogArray<TD> descs ) {
detDesc.detect(input);
for (int i = 0; i < detDesc.getNumberOfFeatures(); i++) {
points.add(detDesc.getLocation(i).copy());
descs.grow().setTo(detDesc.getDescription(i));
}
}
public static void main( String[] args ) {
Class imageType = GrayF32.class;
// Class imageType = GrayU8.class;
// select which algorithms to use
DetectDescribePoint detDesc = FactoryDetectDescribe.
surfStable(new ConfigFastHessian(1, 2, 300, 1, 9, 4, 4), null, null, imageType);
// sift(new ConfigCompleteSift(0,5,600));
ScoreAssociation scorer = FactoryAssociation.defaultScore(detDesc.getDescriptionType());
AssociateDescription associate = FactoryAssociation.greedy(new ConfigAssociateGreedy(true), scorer);
// load and match images
ExampleAssociatePoints app = new ExampleAssociatePoints(detDesc, associate, imageType);
BufferedImage imageA = UtilImageIO.loadImageNotNull(UtilIO.pathExample("stitch/kayak_01.jpg"));
BufferedImage imageB = UtilImageIO.loadImageNotNull(UtilIO.pathExample("stitch/kayak_03.jpg"));
app.associate(imageA, imageB);
}
}