Click or drag to resize
Accord.NET (logo)

BagOfVisualWords Class

Bag of Visual Words
Inheritance Hierarchy
SystemObject
  Accord.MachineLearningParallelLearningBase
    Accord.MachineLearningBaseBagOfWordsBagOfVisualWords, SpeededUpRobustFeaturePoint, Double, IUnsupervisedLearningIClassifierDouble, Int32, Double, Int32, SpeededUpRobustFeaturesDetector, UnmanagedImage
      Accord.ImagingBaseBagOfVisualWordsBagOfVisualWords, SpeededUpRobustFeaturePoint, Double, IUnsupervisedLearningIClassifierDouble, Int32, Double, Int32, SpeededUpRobustFeaturesDetector
        Accord.ImagingBagOfVisualWords

Namespace:  Accord.Imaging
Assembly:  Accord.Vision (in Accord.Vision.dll) Version: 3.8.0
Syntax
[SerializableAttribute]
public class BagOfVisualWords : BaseBagOfVisualWords<BagOfVisualWords, SpeededUpRobustFeaturePoint, double[], IUnsupervisedLearning<IClassifier<double[], int>, double[], int>, SpeededUpRobustFeaturesDetector>
Request Example View Source

The BagOfVisualWords type exposes the following members.

Constructors
Properties
  NameDescription
Public propertyClustering
Gets the clustering algorithm used to create this model.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyDetector
Gets the feature extractor used to identify features in the input data.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyMaxDescriptorsPerInstance
Gets or sets the maximum number of descriptors per image that should be used to learn the codebook. Default is 0 (meaning to use all descriptors).
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyNumberOfDescriptors
Gets or sets the maximum number of descriptors that should be used to learn the codebook. Default is 0 (meaning to use all descriptors).
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyNumberOfInputs
Gets the number of inputs accepted by the model.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyNumberOfOutputs
Gets the number of outputs generated by the model.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyNumberOfWords
Gets the number of words in this codebook.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyParallelOptions
Gets or sets the parallelization options for this algorithm.
(Inherited from ParallelLearningBase.)
Public propertyStatistics
Gets statistics about the last codebook learned.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public propertyToken
Gets or sets a cancellation token that can be used to cancel the algorithm while it is running.
(Inherited from ParallelLearningBase.)
Top
Methods
  NameDescription
Public methodCompute(Bitmap) Obsolete.
Computes the Bag of Words model.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodCompute(TPoint) Obsolete.
Computes the Bag of Words model.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodCompute(Bitmap, Double) Obsolete.
Computes the Bag of Words model.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodStatic memberCreate(Int32)
Creates a Bag-of-Words model using SpeededUpRobustFeaturesDetector and KMeans
Public methodStatic memberCreateTClustering(TClustering)
Creates a Bag-of-Words model using the SURF feature detector and the given clustering algorithm.
Public methodStatic memberCreateTExtractor(TExtractor, Int32)
Creates a Bag-of-Words model using the given feature detector and KMeans.
Public methodStatic memberCreateTExtractor, TClustering(TExtractor, TClustering)
Creates a Bag-of-Words model using the given feature detector and clustering algorithm.
Public methodStatic memberCreateTExtractor, TClustering(IImageFeatureExtractorFeatureDescriptor, TClustering)
Creates a Bag-of-Words model using the given feature detector and clustering algorithm.
Public methodStatic memberCreateTExtractor, TClustering, TFeature(TExtractor, TClustering)
Creates a Bag-of-Words model using the given feature detector and clustering algorithm.
Public methodStatic memberCreateTExtractor, TClustering, TPoint, TFeature(TExtractor, TClustering)
Creates a Bag-of-Words model using the given feature detector and clustering algorithm.
Public methodEquals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Protected methodFor
Executes a parallel for using the feature detector in a thread-safe way.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodGetFeatureVector(ListTFeature) Obsolete.
Gets the codeword representation of a given image.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodGetFeatureVector(Bitmap) Obsolete.
Gets the codeword representation of a given image.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodGetFeatureVector(String) Obsolete.
Gets the codeword representation of a given image.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodGetFeatureVector(UnmanagedImage) Obsolete.
Gets the codeword representation of a given image.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodGetHashCode
Serves as the default hash function.
(Inherited from Object.)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Protected methodInit
Initializes this instance.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Protected methodInnerLearnT
Generic learn method implementation that should work for any input type. This method is useful for re-using code between methods that accept Bitmap, BitmapData, UnmanagedImage, filenames as strings, etc.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodLearn(Bitmap, Double)
Learns a model that can map the given inputs to the desired outputs.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodLearn(String, Double)
Learns a model that can map the given inputs to the desired outputs.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodLearn(TFeature, Double)
Learns a model that can map the given inputs to the desired outputs.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodLearn(TInput, Double)
Learns a model that can map the given inputs to the desired outputs.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodStatic memberLoad(Stream) Obsolete.
Loads a bag of words from a stream.
Public methodStatic memberLoad(String) Obsolete.
Loads a bag of words from a file.
Public methodStatic memberLoadTPoint(Stream) Obsolete.
Loads a bag of words from a stream.
Public methodStatic memberLoadTPoint(String) Obsolete.
Loads a bag of words from a file.
Public methodStatic memberLoadTPoint, TFeature(Stream) Obsolete.
Loads a bag of words from a stream.
Public methodStatic memberLoadTPoint, TFeature(String) Obsolete.
Loads a bag of words from a file.
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodSave(Stream) Obsolete.
Saves the bag of words to a stream.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodSave(String) Obsolete.
Saves the bag of words to a file.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Public methodTransform(Bitmap)
Applies the transformation to an input, producing an associated output.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(Bitmap)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(String)
Applies the transformation to an input, producing an associated output.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(String)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(ListTPoint)
Applies the transformation to an input, producing an associated output.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(TInput)
Applies the transformation to an input, producing an associated output.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(TInput)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(Bitmap, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(Bitmap, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(Bitmap, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(Bitmap, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(String, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(String, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(String, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(String, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfVisualWordsTModel, TFeature, TPoint, TClustering, TExtractor.)
Public methodTransform(IEnumerableTPoint, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(IEnumerableTPoint, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(TInput, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(TInput, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(TInput, Double)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Public methodTransform(TInput, Int32)
Applies the transformation to a set of input vectors, producing an associated set of output vectors.
(Inherited from BaseBagOfWordsTModel, TPoint, TFeature, TClustering, TExtractor, TInput.)
Top
Extension Methods
  NameDescription
Public Extension MethodHasMethod
Checks whether an object implements a method with the given name.
(Defined by ExtensionMethods.)
Public Extension MethodIsEqual
Compares two objects for equality, performing an elementwise comparison if the elements are vectors or matrices.
(Defined by Matrix.)
Public Extension MethodTo(Type)Overloaded.
Converts an object into another type, irrespective of whether the conversion can be done at compile time or not. This can be used to convert generic types to numeric types during runtime.
(Defined by ExtensionMethods.)
Public Extension MethodToTOverloaded.
Converts an object into another type, irrespective of whether the conversion can be done at compile time or not. This can be used to convert generic types to numeric types during runtime.
(Defined by ExtensionMethods.)
Top
Remarks

The bag-of-words (BoW) model can be used to transform data with multiple possible lengths (i.e. words in a text, pixels in an image) into finite-dimensional vectors of fixed length. Those vectors are usually referred as representations as they can be used in place of the original data as if they were the data itself. For example, using Bag-of-Words it becomes possible to transform a set of N images with varying sizes and dimensions into a N x C matrix where C is the number of "visual words" being used to represent each of the N images in the set.

Those rows can then be used in classification, clustering, and any other machine learning tasks where a finite vector representation would be required.

The framework can compute BoW representations for images using any choice of feature extractor and clustering algorithm. By default, the framework uses the SURF features detector and the KMeans clustering algorithm.

Examples

The first example shows how to create and use a BoW with default parameters.

// Ensure results are reproducible
Accord.Math.Random.Generator.Seed = 0;

// The Bag-of-Visual-Words model converts images of arbitrary 
// size into fixed-length feature vectors. In this example, we
// will be setting the codebook size to 10. This means all feature
// vectors that will be generated will have the same length of 10.

// By default, the BoW object will use the sparse SURF as the 
// feature extractor and K-means as the clustering algorithm.

// Create a new Bag-of-Visual-Words (BoW) model
var bow = BagOfVisualWords.Create(numberOfWords: 10);
// Note: a simple BoW model can also be created using
// var bow = new BagOfVisualWords(numberOfWords: 10);

// Get some training images
Bitmap[] images = GetImages();

// Compute the model
bow.Learn(images);

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(images);

// We can also check some statistics about the dataset:
int numberOfImages = bow.Statistics.TotalNumberOfInstances; // 6

// Statistics about all the descriptors that have been extracted:
int totalDescriptors = bow.Statistics.TotalNumberOfDescriptors; // 4132
double totalMean = bow.Statistics.TotalNumberOfDescriptorsPerInstance.Mean; // 688.66666666666663
double totalVar = bow.Statistics.TotalNumberOfDescriptorsPerInstance.Variance; // 96745.866666666669
IntRange totalRange = bow.Statistics.TotalNumberOfDescriptorsPerInstanceRange; // [409, 1265]

// Statistics only about the descriptors that have been actually used:
int takenDescriptors = bow.Statistics.NumberOfDescriptorsTaken; // 4132
double takenMean = bow.Statistics.NumberOfDescriptorsTakenPerInstance.Mean; // 688.66666666666663
double takenVar = bow.Statistics.NumberOfDescriptorsTakenPerInstance.Variance; // 96745.866666666669
IntRange takenRange = bow.Statistics.NumberOfDescriptorsTakenPerInstanceRange; // [409, 1265]

After the representations have been extracted, it is possible to use them in arbitrary machine learning tasks, such as classification:

// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 10000 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output);

By default, the BoW uses K-Means to cluster feature vectors. The next example demonstrates how to use a different clustering algorithm when computing the BoW, including the Binary Split algorithm.

// Ensure results are reproducible
Accord.Math.Random.Generator.Seed = 0;

// The Bag-of-Visual-Words model converts images of arbitrary 
// size into fixed-length feature vectors. In this example, we
// will be setting the codebook size to 10. This means all feature
// vectors that will be generated will have the same length of 10.

// By default, the BoW object will use the sparse SURF as the 
// feature extractor and K-means as the clustering algorithm.
// In this example, we will use the Binary-Split clustering
// algorithm instead.

// Create a new Bag-of-Visual-Words (BoW) model
var bow = BagOfVisualWords.Create(new BinarySplit(10));

// Since we are using generics, we can setup properties 
// of the binary split clustering algorithm directly:
bow.Clustering.ComputeProportions = true;
bow.Clustering.ComputeCovariances = false;

// Get some training images
Bitmap[] images = GetImages();

// Compute the model
bow.Learn(images);

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(images);
// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 10000 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output); // should be 0

By default, the BoW uses the SURF feature detector to extract sparse features from the images. However, it is also possible to use other detectors, including dense detectors such as HistogramsOfOrientedGradients.

Accord.Math.Random.Generator.Seed = 0;

// The Bag-of-Visual-Words model converts images of arbitrary 
// size into fixed-length feature vectors. In this example, we
// will be setting the codebook size to 10. This means all feature
// vectors that will be generated will have the same length of 10.

// By default, the BoW object will use the sparse SURF as the 
// feature extractor and K-means as the clustering algorithm.
// In this example, we will use the HOG feature extractor
// and the Binary-Split clustering algorithm instead. However, 
// this is just an example: the best features and the best clustering 
// algorithm might need to be found through experimentation. Please
// also try with KMeans first to obtain a baseline value.

// Create a new Bag-of-Visual-Words (BoW) model using HOG features
var bow = BagOfVisualWords.Create(new HistogramsOfOrientedGradients(), new BinarySplit(10));

// Get some training images
Bitmap[] images = GetImages();

// Compute the model
bow.Learn(images);

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(images);
// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 100 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output); // should be 0

Or this also simple case using the FREAK detector and the BinarySplit clustering algorithm:

// Ensure results are reproducible
Accord.Math.Random.Generator.Seed = 0;

// The Bag-of-Visual-Words model converts images of arbitrary 
// size into fixed-length feature vectors. In this example, we
// will be setting the codebook size to 10. This means all feature
// vectors that will be generated will have the same length of 10.

// By default, the BoW object will use the sparse SURF as the 
// feature extractor and K-means as the clustering algorithm.
// In this example, we will use the FREAK feature extractor
// and the Binary-Split clustering algorithm instead.

// Create a new Bag-of-Visual-Words (BoW) model using FREAK binary features
var bow = BagOfVisualWords.Create(new FastRetinaKeypointDetector(), new BinarySplit(10));

// Get some training images
Bitmap[] images = GetImages();

// Compute the model
bow.Learn(images);

bow.ParallelOptions.MaxDegreeOfParallelism = 1;

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(images);
// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 1000 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output); // should be 0

More advanced use cases are also supported. For example, some image patches can be represented using different data representations, such as byte vectors. In this case, it is still possible to use the BoW using an appropriate clustering algorithm that doesn't depend on Euclidean distances.

// Ensure results are reproducible
Accord.Math.Random.Generator.Seed = 0;

// The Bag-of-Visual-Words model converts images of arbitrary 
// size into fixed-length feature vectors. In this example, we
// will be setting the codebook size to 10. This means all feature
// vectors that will be generated will have the same length of 10.

// By default, the BoW object will use the sparse SURF as the 
// feature extractor and K-means as the clustering algorithm.
// In this example, we will use the FREAK feature extractor
// and the K-Modes clustering algorithm instead.

// Create a new Bag-of-Visual-Words (BoW) model using FREAK binary features
var bow = BagOfVisualWords.Create<FastRetinaKeypointDetector, KModes<byte>, byte[]>(
    new FastRetinaKeypointDetector(), new KModes<byte>(10, new Hamming()));

// Get some training images
Bitmap[] images = GetImages();

// Compute the model
bow.Learn(images);

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(images);
// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 1000 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output); // should be 0

Other more specialized feature extractors can also be used, such as Haralick texture feature extractors for performing texture classification.

// Ensure results are reproducible
Accord.Math.Random.Generator.Seed = 0;

// The Bag-of-Visual-Words model converts images of arbitrary 
// size into fixed-length feature vectors. In this example, we
// will be setting the codebook size to 3. This means all feature
// vectors that will be generated will have the same length of 3.

// By default, the BoW object will use the sparse SURF as the 
// feature extractor and K-means as the clustering algorithm.
// In this example, we will use the Haralick feature extractor.

// Create a new Bag-of-Visual-Words (BoW) model using Haralick features
var bow = BagOfVisualWords.Create(new Haralick()
{
    CellSize = 256, // divide images in cells of 256x256 pixels
    Mode = HaralickMode.AverageWithRange,
}, new KMeans(3));

// Generate some training images. Haralick is best for classifying
// textures, so we will be generating examples of wood and clouds:
var woodenGenerator = new WoodTexture();
var cloudsGenerator = new CloudsTexture();

Bitmap[] images = new[]
{
    woodenGenerator.Generate(512, 512).ToBitmap(),
    woodenGenerator.Generate(512, 512).ToBitmap(),
    woodenGenerator.Generate(512, 512).ToBitmap(),

    cloudsGenerator.Generate(512, 512).ToBitmap(),
    cloudsGenerator.Generate(512, 512).ToBitmap(),
    cloudsGenerator.Generate(512, 512).ToBitmap()
};

// Compute the model
bow.Learn(images);

bow.ParallelOptions.MaxDegreeOfParallelism = 1;

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(images);
// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 100 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output); // should be 0

In some applications, learning a BoW with the default settings might need a large amount of memory to be available. In those cases, it is possible to reduce the memory and CPU requirements for the learning phase using the NumberOfDescriptors and MaxDescriptorsPerInstance properties. It is also possible to avoid loading all images at once by feeding the algorithm with the image filenames instead of their Bitmap representations:

// Ensure results are reproducible
Accord.Math.Random.Generator.Seed = 0;

// Depending on the problem we are trying to tackle, learning a BoW might require 
// large amounts of available memory. In those cases, we can alleviate the amount
// of memory required by using only a subsample of the training datasete to learn
// the model. Likewise, we can also load images from the disk on-demand instead of
// having to load all of them right at the beginning.

// Create a new Bag-of-Visual-Words (BoW) model
var bow = BagOfVisualWords.Create(numberOfWords: 10);

// We will learn the codebooks from only 25 descriptors, which
// will be randomly selected from the multiple training images
bow.NumberOfDescriptors = 1000; // Note: in the real world, use >10,000 samples

// We will load at most 5 descriptors from each image. This means
// that we will only keep 5 descriptors per image at maximum in 
// memory at a given time.
bow.MaxDescriptorsPerInstance = 200; // Note: In the real world, use >1,000 samples

// Get some training images. Here, instead of loading Bitmaps as in
// the other examples, we will just specify their paths in the disk:
string[] filenames =
{
    Path.Combine(basePath, "flower01.jpg"),
    Path.Combine(basePath, "flower02.jpg"),
    Path.Combine(basePath, "flower03.jpg"),
    Path.Combine(basePath, "flower04.jpg"),
    Path.Combine(basePath, "flower05.jpg"),
    Path.Combine(basePath, "flower06.jpg"),
};

// Compute the model
bow.Learn(filenames);

// After this point, we will be able to translate
// images into double[] feature vectors using
double[][] features = bow.Transform(filenames);

// We can also check some statistics about the dataset:
int numberOfImages = bow.Statistics.TotalNumberOfInstances; // 6

// Statistics about all the descriptors that have been extracted:
int totalDescriptors = bow.Statistics.TotalNumberOfDescriptors; // 4132
double totalMean = bow.Statistics.TotalNumberOfDescriptorsPerInstance.Mean; // 688.66666666666663
double totalVar = bow.Statistics.TotalNumberOfDescriptorsPerInstance.Variance; // 96745.866666666669
IntRange totalRange = bow.Statistics.TotalNumberOfDescriptorsPerInstanceRange; // [409, 1265]

// Statistics only about the descriptors that have been actually used:
int takenDescriptors = bow.Statistics.NumberOfDescriptorsTaken; // 1000
double takenMean = bow.Statistics.NumberOfDescriptorsTakenPerInstance.Mean; // 200
double takenVar = bow.Statistics.NumberOfDescriptorsTakenPerInstance.Variance; // 0
IntRange takenRange = bow.Statistics.NumberOfDescriptorsTakenPerInstanceRange; // [200, 200]
// Now, the features can be used to train any classification
// algorithm as if they were the images themselves. For example,
// let's assume the first three images belong to a class and
// the second three to another class. We can train an SVM using

int[] labels = { -1, -1, -1, +1, +1, +1 };

// Create the SMO algorithm to learn a Linear kernel SVM
var teacher = new SequentialMinimalOptimization<Linear>()
{
    Complexity = 10000 // make a hard margin SVM
};

// Obtain a learned machine
var svm = teacher.Learn(features, labels);

// Use the machine to classify the features
bool[] output = svm.Decide(features);

// Compute the error between the expected and predicted labels
double error = new ZeroOneLoss(labels).Loss(output);
See Also