net.semanticmetadata.lire.builders.AbstractLocalDocumentBuilder.java Source code

Java tutorial

Introduction

Here is the source code for net.semanticmetadata.lire.builders.AbstractLocalDocumentBuilder.java

Source

/*
 * This file is part of the LIRE project: http://lire-project.net
 * LIRE is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * LIRE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LIRE; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * We kindly ask you to refer the any or one of the following publications in
 * any publication mentioning or employing Lire:
 *
 * Lux Mathias, Savvas A. Chatzichristofis. Lire: Lucene Image Retrieval -
 * An Extensible Java CBIR Library. In proceedings of the 16th ACM International
 * Conference on Multimedia, pp. 1085-1088, Vancouver, Canada, 2008
 * URL: http://doi.acm.org/10.1145/1459359.1459577
 *
 * Lux Mathias. Content Based Image Retrieval with LIRE. In proceedings of the
 * 19th ACM International Conference on Multimedia, pp. 735-738, Scottsdale,
 * Arizona, USA, 2011
 * URL: http://dl.acm.org/citation.cfm?id=2072432
 *
 * Mathias Lux, Oge Marques. Visual Information Retrieval using Java and LIRE
 * Morgan & Claypool, 2013
 * URL: http://www.morganclaypool.com/doi/abs/10.2200/S00468ED1V01Y201301ICR025
 */

package net.semanticmetadata.lire.builders;

import net.semanticmetadata.lire.aggregators.AbstractAggregator;
import net.semanticmetadata.lire.aggregators.BOVW;
import net.semanticmetadata.lire.classifiers.Cluster;
import net.semanticmetadata.lire.imageanalysis.features.LocalFeature;
import net.semanticmetadata.lire.imageanalysis.features.LocalFeatureExtractor;
import net.semanticmetadata.lire.indexers.parallel.ExtractorItem;
import net.semanticmetadata.lire.utils.ImageUtils;
import org.apache.lucene.document.*;

import java.awt.image.BufferedImage;
import java.util.*;

/**
 * This class is used by the LocalDocumentBuilder and the SimpleDocumentBuilder to create
 * Lucene Documents for Local Features.
 * Created by Nektarios on 03/06/2015.
 *
 * @author Nektarios Anagnostopoulos, nek.anag@gmail.com
 * (c) 2015 by Nektarios Anagnostopoulos
 */
public abstract class AbstractLocalDocumentBuilder implements DocumentBuilder {
    //    enum HashingMode {BitSampling, LSH}
    //    protected HashingMode hashingMode = HashingMode.BitSampling;
    //    private boolean hashingEnabled = false;

    protected HashMap<ExtractorItem, LinkedList<Cluster[]>> extractorItems = new HashMap<ExtractorItem, LinkedList<Cluster[]>>(
            10);
    protected HashMap<ExtractorItem, HashMap<Integer, String[]>> fieldNamesDictionary = new HashMap<ExtractorItem, HashMap<Integer, String[]>>(
            10);
    protected AbstractAggregator aggregator = new BOVW();
    protected boolean docsCreated = false;

    /**
     * Images are resized so as not to exceed the {@link DocumentBuilder#MAX_IMAGE_DIMENSION}, after that
     * features are extracted using the given localFeatureExtractor.
     * @param image is the image
     * @param localFeatureExtractor selected local feature extractor
     * @return the input localFeatureExtractor
     */
    public LocalFeatureExtractor extractLocalFeatures(BufferedImage image,
            LocalFeatureExtractor localFeatureExtractor) {
        assert (image != null);
        // Scaling image is especially with the correlogram features very important!
        // All images are scaled to guarantee a certain upper limit for indexing.
        if (Math.max(image.getHeight(), image.getWidth()) > DocumentBuilder.MAX_IMAGE_DIMENSION) {
            image = ImageUtils.scaleImage(image, DocumentBuilder.MAX_IMAGE_DIMENSION);
        }

        localFeatureExtractor.extract(image);
        return localFeatureExtractor;
    }

    /**
     * Extracts the features and returns the Lucene Fields with the vector representation of the selected image.
     * @param image is the selected image.
     * @param extractorItem is the selected extractor.
     * @param listOfCodebooks is the list which can contain one or more codebooks to be used for the aggregation of the local features.
     * @return Lucene Fields with the vector representation of the selected image.
     */
    private Field[] getLocalDescriptorFields(BufferedImage image, ExtractorItem extractorItem,
            LinkedList<Cluster[]> listOfCodebooks) {
        LocalFeatureExtractor localFeatureExtractor = extractLocalFeatures(image,
                (LocalFeatureExtractor) extractorItem.getExtractorInstance());

        return createLocalDescriptorFields(localFeatureExtractor.getFeatures(), extractorItem, listOfCodebooks);
    }

    /**
     * Creates the Lucene Fiels with the vector representation of list of local features.
     * @param listOfLocalFeatures is the list of local features.
     * @param extractorItem is the extractor that was used to extract the features.
     * @param listOfCodebooks is the list which can contain one or more codebooks to be used for the aggregation of the local features.
     * @return Lucene Fields with the vector representation of the list of local features.
     */
    public Field[] createLocalDescriptorFields(List<? extends LocalFeature> listOfLocalFeatures,
            ExtractorItem extractorItem, LinkedList<Cluster[]> listOfCodebooks) {
        Field[] result = new Field[listOfCodebooks.size() * 2];
        int count = 0;
        for (Cluster[] codebook : listOfCodebooks) {
            aggregator.createVectorRepresentation(listOfLocalFeatures, codebook);
            result[count] = new StoredField(fieldNamesDictionary.get(extractorItem).get(codebook.length)[0],
                    aggregator.getByteVectorRepresentation());
            result[count + 1] = new TextField(fieldNamesDictionary.get(extractorItem).get(codebook.length)[1],
                    aggregator.getStringVectorRepresentation(), Field.Store.YES);
            count += 2;
        }

        return result;
    }

    /**
     * @param image the image to analyze.
     * @return Lucene Fields with the vector representation of the selected image.
     */
    @Override
    public Field[] createDescriptorFields(BufferedImage image) {
        docsCreated = true;
        LinkedList<Field> resultList = new LinkedList<Field>();
        Field[] fields;
        if (extractorItems.size() > 0) {
            for (Map.Entry<ExtractorItem, LinkedList<Cluster[]>> extractorItemEntry : extractorItems.entrySet()) {
                fields = getLocalDescriptorFields(image, extractorItemEntry.getKey(),
                        extractorItemEntry.getValue());

                Collections.addAll(resultList, fields);
            }
        }

        return resultList.toArray(new Field[resultList.size()]);
    }

    /**
     * @param image the image to index. Cannot be NULL.
     * @param identifier an id for the image, for instance the filename or a URL. Can be NULL.
     * @return a Lucene Document.
     */
    @Override
    public Document createDocument(BufferedImage image, String identifier) {
        Document doc = new Document();

        if (identifier != null) {
            doc.add(new StringField(DocumentBuilder.FIELD_NAME_IDENTIFIER, identifier, Field.Store.YES));
        }

        Field[] fields = createDescriptorFields(image);
        for (Field field : fields) {
            doc.add(field);
        }

        return doc;
    }
}