All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openimaj.image.annotation.evaluation.datasets.Caltech101 Maven / Gradle / Ivy

/**
 * Copyright (c) 2011, The University of Southampton and the individual contributors.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *   * 	Redistributions of source code must retain the above copyright notice,
 * 	this list of conditions and the following disclaimer.
 *
 *   *	Redistributions in binary form must reproduce the above copyright notice,
 * 	this list of conditions and the following disclaimer in the documentation
 * 	and/or other materials provided with the distribution.
 *
 *   *	Neither the name of the University of Southampton nor the names of its
 * 	contributors may be used to endorse or promote products derived from this
 * 	software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.openimaj.image.annotation.evaluation.datasets;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import org.apache.commons.io.FileUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.openimaj.data.DataUtils;
import org.openimaj.data.dataset.VFSGroupDataset;
import org.openimaj.data.dataset.VFSListDataset;
import org.openimaj.data.identity.Identifiable;
import org.openimaj.experiment.annotations.DatasetDescription;
import org.openimaj.image.Image;
import org.openimaj.image.ImageProvider;
import org.openimaj.image.ImageUtilities;
import org.openimaj.io.InputStreamObjectReader;
import org.openimaj.io.ObjectReader;
import org.openimaj.math.geometry.point.Point2dImpl;
import org.openimaj.math.geometry.shape.Polygon;
import org.openimaj.math.geometry.shape.Rectangle;

import com.jmatio.io.MatFileReader;
import com.jmatio.types.MLDouble;

/**
 * The CalTech101 image dataset. Contains 102 classes of image (101 objects +
 * background), and (for most images) outlines and bounding boxes of the object.
 * Images are approximately 300x200 pixels in size.
 * 
 * @author Jonathon Hare ([email protected])
 */
@DatasetDescription(
		name = "CalTech101",
		description = "Pictures of objects belonging to 101 categories. " +
				"About 40 to 800 images per category. Most categories have about " +
				"50 images. The size of each image is roughly 300 x 200 pixels.",
		creator = "Fei-Fei Li, Marco Andreetto, and Marc 'Aurelio Ranzato",
		url = "http://www.vision.caltech.edu/Image_Datasets/Caltech101/",
		downloadUrls = {
				"http://datasets.openimaj.org/Caltech101/101_ObjectCategories.zip",
				"http://datasets.openimaj.org/Caltech101/Annotations.zip"
		})
public class Caltech101 {
	private static final String IMAGES_ZIP = "Caltech101/101_ObjectCategories.zip";
	private static final String IMAGES_DOWNLOAD_URL = "http://datasets.openimaj.org/Caltech101/101_ObjectCategories.zip";
	private static final String ANNOTATIONS_ZIP = "Caltech101/Annotations.zip";
	private static final String ANNOTATIONS_DOWNLOAD_URL = "http://datasets.openimaj.org/Caltech101/Annotations.zip";

	private Caltech101() {
	}

	/**
	 * Get a dataset of the Caltech 101 images. If the dataset hasn't been
	 * downloaded, it will be fetched automatically and stored in the OpenIMAJ
	 * data directory. The images in the dataset are grouped by their class.
	 * 
	 * @see DataUtils#getDataDirectory()
	 * 
	 * @param reader
	 * @return a dataset of images
	 * @throws IOException
	 *             if a problem occurs loading the dataset
	 */
	public static > VFSGroupDataset getImages(InputStreamObjectReader reader)
			throws IOException
	{
		return new VFSGroupDataset(downloadAndGetImagePath(), reader);
	}

	private static String downloadAndGetImagePath() throws IOException {
		final File dataset = DataUtils.getDataLocation(IMAGES_ZIP);

		if (!(dataset.exists())) {
			dataset.getParentFile().mkdirs();
			FileUtils.copyURLToFile(new URL(IMAGES_DOWNLOAD_URL), dataset);
		}

		return "zip:file:" + dataset.toString() + "!101_ObjectCategories/";
	}

	private static String downloadAndGetAnnotationPath() throws IOException {
		final File dataset = DataUtils.getDataLocation(ANNOTATIONS_ZIP);

		if (!(dataset.exists())) {
			dataset.getParentFile().mkdirs();
			FileUtils.copyURLToFile(new URL(ANNOTATIONS_DOWNLOAD_URL), dataset);
		}

		return "zip:file:" + dataset.toString() + "!Annotations/";
	}

	/**
	 * A record in the Caltech 101 dataset. Contains the image together with
	 * (optional) metadata on the bounds of the object in the image as well as
	 * the class of object in the image.
	 * 
	 * @author Jonathon Hare ([email protected])
	 * 
	 * @param 
	 *            The type of image that is loaded
	 */
	public static abstract class Record> implements Identifiable, ImageProvider {
		private Rectangle bounds;
		private Polygon contour;
		private String id;
		private String objectClass;

		protected Record(FileObject image) throws FileSystemException, IOException {
			final FileSystemManager fsManager = VFS.getManager();
			final FileObject imagesBase = fsManager.resolveFile(downloadAndGetImagePath());
			final FileObject annotationsBase = fsManager.resolveFile(downloadAndGetAnnotationPath());

			// get the id
			id = imagesBase.getName().getRelativeName(image.getName());

			// the class
			objectClass = image.getParent().getName().getBaseName();

			// find the annotation file
			final String annotationFileName = id.replace("image_", "annotation_").replace(".jpg", ".mat");
			final FileObject annotationFile = annotationsBase.resolveFile(annotationFileName);
			parseAnnotations(annotationFile);
		}

		private void parseAnnotations(FileObject annotationFile) throws IOException {
			if (!annotationFile.exists()) {
				return;
			}

			final MatFileReader reader = new MatFileReader(annotationFile.getContent().getInputStream());

			final MLDouble boxes = (MLDouble) reader.getMLArray("box_coord");
			this.bounds = new Rectangle(
					(float) (double) boxes.getReal(2) - 1,
					(float) (double) boxes.getReal(0) - 1,
					(float) (boxes.getReal(3) - boxes.getReal(2)) - 1,
					(float) (boxes.getReal(1) - boxes.getReal(0)) - 1);

			final double[][] contourData = ((MLDouble) reader.getMLArray("obj_contour")).getArray();
			this.contour = new Polygon();
			for (int i = 0; i < contourData[0].length; i++) {
				contour.points.add(
						new Point2dImpl((float) contourData[0][i] + bounds.x - 1,
								(float) contourData[1][i] + bounds.y - 1)
						);
			}
			contour.close();
		}

		@Override
		public String getID() {
			return id;
		}

		/**
		 * Get the bounds rectangle if it is available
		 * 
		 * @return the bounds
		 */
		public Rectangle getBounds() {
			return bounds;
		}

		/**
		 * Get the object polygon if it is available.
		 * 
		 * @return the contour
		 */
		public Polygon getContour() {
			return contour;
		}

		/**
		 * Get the class of the object depicted in the image.
		 * 
		 * @return the class
		 */
		public String getObjectClass() {
			return objectClass;
		}
	}

	/**
	 * An {@link ObjectReader} for {@link Record}s.
	 * 
	 * @author Jonathon Hare ([email protected])
	 * 
	 * @param 
	 *            Type of image being read
	 */
	private static class RecordReader> implements ObjectReader, FileObject> {
		private VFSListDataset.FileObjectISReader imageReader;

		public RecordReader(InputStreamObjectReader reader) {
			this.imageReader = new VFSListDataset.FileObjectISReader(reader);
		}

		@Override
		public Record read(final FileObject source) throws IOException {
			return new Record(source) {

				@Override
				public IMAGE getImage() {
					try {
						return imageReader.read(source);
					} catch (final IOException e) {
						throw new RuntimeException(e);
					}
				}
			};
		}

		@Override
		public boolean canRead(FileObject source, String name) {
			InputStream stream = null;
			try {
				stream = source.getContent().getInputStream();

				return ImageUtilities.FIMAGE_READER.canRead(stream, source.getName().getBaseName());
			} catch (final FileSystemException e) {
				return false;
			} finally {
				if (stream != null) {
					try {
						stream.close();
					} catch (final IOException e) {
					}
				}
			}
		}
	}

	/**
	 * Get a dataset of the Caltech 101 images and metadata. If the dataset
	 * hasn't been downloaded, it will be fetched automatically and stored in
	 * the OpenIMAJ data directory. The images in the dataset are grouped by
	 * their class.
	 * 
	 * @see DataUtils#getDataDirectory()
	 * 
	 * @param reader
	 *            a reader for reading images (usually a
	 *            {@link ImageUtilities#FIMAGE_READER} or
	 *            {@link ImageUtilities#MBFIMAGE_READER}).
	 * @return a dataset of images and metadate
	 * @throws IOException
	 *             if a problem occurs loading the dataset
	 */
	public static > VFSGroupDataset> getData(
			InputStreamObjectReader reader) throws IOException
	{
		return new VFSGroupDataset>(downloadAndGetImagePath(), new RecordReader(reader));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy