Difference between revisions of "Example Scene Recognition"
From BoofCV
Jump to navigationJump to searchm |
m |
||
Line 12: | Line 12: | ||
Concepts: | Concepts: | ||
* Template Matching | * Template Matching | ||
Related: | |||
* [[Example_Loop_Closure| Loop Closure]] | |||
Videos: | Videos: |
Latest revision as of 16:41, 2 September 2022
Example of scene recognition in action. The two closest matches to the top image are found. This works well even with very large databases, e.g. 100,000 images. |
---|
Example Code:
Concepts:
- Template Matching
Related:
Videos:
Example Code
/**
* In BoofCV, scene recognition [1] refers to the problem of trying to identify photos of the same scene (not a single
* object in the image) from different perspectives. This is of interest if you want to organize your photos, find
* images to create a mosaic from, or cluster photos for 3D reconstruction. Solutions to this problem tend to
* emphasise fast accurate retrieval from large databases.
*
* [1] As far as I can tell there is no universal terminology for this specific sub problem. It is sometimes lumped
* under Content Based Image Retrieval (CBIR), which is a very generic term.
*
* @author Peter Abeles
*/
public class ExampleSceneRecognition {
public static void main( String[] args ) {
String imagePath = UtilIO.pathExample("recognition/scene");
List<String> images = UtilIO.listByPrefix(imagePath, null, ".jpg");
Collections.sort(images);
SceneRecognition<GrayU8> recognizer;
// Except for real-time applications or when there are more than a few hundred images, you might want to
// just learn the dictionary from scratch
var saveDirectory = new File("example_recognition");
// Tell it to process gray U8 images
ImageType<GrayU8> imageType = ImageType.SB_U8;
// Used to look up images one at a time from various sources. In this case a list of images.
var imageIterator = new ImageFileListIterator<>(images, imageType);
if (false) {
// Set the line above to true and it will download a pre-built model. Useful when you have a lot of images
// or simply want to skip the learning step
System.out.println("Downloading pre-built model");
recognizer = RecognitionIO.downloadDefaultSceneRecognition(new File("downloaded_models"), imageType);
recognizer.setVerbose(System.out, BoofMiscOps.hashSet(BoofVerbose.RECURSIVE));
} else if (saveDirectory.exists()) {
System.out.println("Loading previously generated model");
recognizer = RecognitionIO.loadFeatureToScene(saveDirectory, imageType);
recognizer.setVerbose(System.out, BoofMiscOps.hashSet(BoofVerbose.RECURSIVE));
} else {
// If many applications, learning a new model is a small fraction of the compute time and since its
// fit to the images it will be more accurate than a generic pre-built model
System.out.println("Creating a new model");
var config = new ConfigFeatureToSceneRecognition();
// Use a hierarchical vocabulary tree, which is very fast and also one of the more accurate approaches
config.typeRecognize = ConfigFeatureToSceneRecognition.Type.NISTER_2006;
config.recognizeNister2006.learningMinimumPointsForChildren.setFixed(20);
recognizer = FactorySceneRecognition.createFeatureToScene(config, imageType);
// This will print out a lot of debugging information to stdout
recognizer.setVerbose(System.out, BoofMiscOps.hashSet(BoofVerbose.RECURSIVE));
// Learn the model from the initial set of images
recognizer.learnModel(imageIterator);
}
// See if the recognition algorithm already has images loaded in to it
if (recognizer.getImageIds(null).isEmpty()) {
// Add images to the database
System.out.println("Adding images to the database");
imageIterator.reset();
while (imageIterator.hasNext()) {
GrayU8 image = imageIterator.next();
recognizer.addImage(images.get(imageIterator.getIndex()), image);
}
// This saves the model with the image database to disk
System.out.println("Saving model");
BoofMiscOps.profile(() -> RecognitionIO.saveFeatureToScene(
(WrapFeatureToSceneRecognition<GrayU8, ?>)recognizer, saveDirectory), "");
}
var gui = new ListDisplayPanel();
// Specifies which image it will try to look up. In the example, related images are in sets of 3.
int queryImage = 9;
// Add the target which the other images are being matched against
gui.addImage(UtilImageIO.loadImageNotNull(images.get(queryImage)), "Query", ScaleOptions.ALL);
// Look up images
var matches = new DogArray<>(SceneRecognition.Match::new);
recognizer.query(imageIterator.loadImage(queryImage),/* filter */ ( id ) -> true,/* limit */ 5, matches);
for (int i = 0; i < matches.size; i++) {
String file = matches.get(i).id;
double error = matches.get(i).error;
BufferedImage image = UtilImageIO.loadImageNotNull(file);
String name = FilenameUtils.getBaseName(new File(file).getName());
gui.addImage(image, String.format("%20s Error %6.3f", name, error), ScaleOptions.ALL);
}
System.out.println("Total images = " + images.size());
System.out.println(images.get(queryImage) + " -> " + matches.get(0).id + " matches.size=" + matches.size);
ShowImages.showWindow(gui, "Similar Images by Features", true);
}
}