import io
import tarfile
from pathlib import Path
from PIL import Image as PILImage
from stable_datasets.schema import ClassLabel, DatasetInfo, DatasetSource, DownloadInfo, Features, Version
from stable_datasets.schema import Image as ImageFeature
from stable_datasets.utils import BaseDatasetBuilder
[docs]
class Caltech256(BaseDatasetBuilder):
"""
Caltech-256
A collection of 30,607 training images with 256 categories and one additional clutter
category (for testing background rejection) created by Griffin, Holub, and Perona (2007).
Each category has a minimum of 80 images. There are 30,185 RGB and 422 grayscale images,
all of which have been converted to contain 3 color channels, but the image sizes
remain inconsistent.
"""
VERSION = Version("1.0.0")
SOURCE = DatasetSource(
homepage="https://data.caltech.edu/records/nyy15-4j048",
assets={
"train": DownloadInfo(
url="https://data.caltech.edu/records/nyy15-4j048/files/256_ObjectCategories.tar?download=1",
checksum="md5:67b4f42ca05d46448c6bb8ecd2220f6d",
filename="256_ObjectCategories.tar",
),
},
citation="""@article{griffin_holub_perona_2007,
title = {Caltech-256 Object Category Dataset},
publisher = {California Institute of Technology},
author = {Griffin, Gregory and Holub, Alex and Perona, Pietro},
year = {2007},
month = {mar}}""",
license="Creative Commons Attribution 4.0 International",
)
def _info(self):
"""Returns information about the Caltech-256 dataset"""
return DatasetInfo(
features=Features(
{
"image": ImageFeature(),
"label": ClassLabel(names=self._labels()),
}
),
description="Caltech-256 contains 256 object categories and an additional clutter category, for 30,607 images in total.",
supervised_keys=("image", "label"),
homepage=self.SOURCE["homepage"],
citation=self.SOURCE["citation"],
license=self.SOURCE["license"],
)
def _generate_examples(self, data_path, split):
"""Generate examples from the .tar archive."""
with tarfile.open(data_path, "r") as tar:
for member in tar:
# check member type
path = Path(member.name)
if not member.isfile() or path.suffix != ".jpg":
continue
# get label from path (e.g. "001.ak47/001_0001.jpg")
label = path.parent.suffix[1:]
# read image bytes
with tar.extractfile(member) as f:
image_bytes = f.read()
# ensure all images are RGB (lazy loading, only decodes if necessary)
pil_image = PILImage.open(io.BytesIO(image_bytes))
if pil_image.mode != "RGB":
image_bytes = ImageFeature().encode(pil_image.convert("RGB"))
# yield training example, using path as key for traceability
key = str(path.relative_to(path.parents[1]))
yield key, {"image": image_bytes, "label": label}
@staticmethod
def _labels():
"""Returns the list of Caltech-256 labels, plus an additional clutter class (257 classes)."""
return [
"ak47",
"american-flag",
"backpack",
"baseball-bat",
"baseball-glove",
"basketball-hoop",
"bat",
"bathtub",
"bear",
"beer-mug",
"billiards",
"binoculars",
"birdbath",
"blimp",
"bonsai-101",
"boom-box",
"bowling-ball",
"bowling-pin",
"boxing-glove",
"brain-101",
"breadmaker",
"buddha-101",
"bulldozer",
"butterfly",
"cactus",
"cake",
"calculator",
"camel",
"cannon",
"canoe",
"car-tire",
"cartman",
"cd",
"centipede",
"cereal-box",
"chandelier-101",
"chess-board",
"chimp",
"chopsticks",
"cockroach",
"coffee-mug",
"coffin",
"coin",
"comet",
"computer-keyboard",
"computer-monitor",
"computer-mouse",
"conch",
"cormorant",
"covered-wagon",
"cowboy-hat",
"crab-101",
"desk-globe",
"diamond-ring",
"dice",
"dog",
"dolphin-101",
"doorknob",
"drinking-straw",
"duck",
"dumb-bell",
"eiffel-tower",
"electric-guitar-101",
"elephant-101",
"elk",
"ewer-101",
"eyeglasses",
"fern",
"fighter-jet",
"fire-extinguisher",
"fire-hydrant",
"fire-truck",
"fireworks",
"flashlight",
"floppy-disk",
"football-helmet",
"french-horn",
"fried-egg",
"frisbee",
"frog",
"frying-pan",
"galaxy",
"gas-pump",
"giraffe",
"goat",
"golden-gate-bridge",
"goldfish",
"golf-ball",
"goose",
"gorilla",
"grand-piano-101",
"grapes",
"grasshopper",
"guitar-pick",
"hamburger",
"hammock",
"harmonica",
"harp",
"harpsichord",
"hawksbill-101",
"head-phones",
"helicopter-101",
"hibiscus",
"homer-simpson",
"horse",
"horseshoe-crab",
"hot-air-balloon",
"hot-dog",
"hot-tub",
"hourglass",
"house-fly",
"human-skeleton",
"hummingbird",
"ibis-101",
"ice-cream-cone",
"iguana",
"ipod",
"iris",
"jesus-christ",
"joy-stick",
"kangaroo-101",
"kayak",
"ketch-101",
"killer-whale",
"knife",
"ladder",
"laptop-101",
"lathe",
"leopards-101",
"license-plate",
"lightbulb",
"light-house",
"lightning",
"llama-101",
"mailbox",
"mandolin",
"mars",
"mattress",
"megaphone",
"menorah-101",
"microscope",
"microwave",
"minaret",
"minotaur",
"motorbikes-101",
"mountain-bike",
"mushroom",
"mussels",
"necktie",
"octopus",
"ostrich",
"owl",
"palm-pilot",
"palm-tree",
"paperclip",
"paper-shredder",
"pci-card",
"penguin",
"people",
"pez-dispenser",
"photocopier",
"picnic-table",
"playing-card",
"porcupine",
"pram",
"praying-mantis",
"pyramid",
"raccoon",
"radio-telescope",
"rainbow",
"refrigerator",
"revolver-101",
"rifle",
"rotary-phone",
"roulette-wheel",
"saddle",
"saturn",
"school-bus",
"scorpion-101",
"screwdriver",
"segway",
"self-propelled-lawn-mower",
"sextant",
"sheet-music",
"skateboard",
"skunk",
"skyscraper",
"smokestack",
"snail",
"snake",
"sneaker",
"snowmobile",
"soccer-ball",
"socks",
"soda-can",
"spaghetti",
"speed-boat",
"spider",
"spoon",
"stained-glass",
"starfish-101",
"steering-wheel",
"stirrups",
"sunflower-101",
"superman",
"sushi",
"swan",
"swiss-army-knife",
"sword",
"syringe",
"tambourine",
"teapot",
"teddy-bear",
"teepee",
"telephone-box",
"tennis-ball",
"tennis-court",
"tennis-racket",
"theodolite",
"toaster",
"tomato",
"tombstone",
"top-hat",
"touring-bike",
"tower-pisa",
"traffic-light",
"treadmill",
"triceratops",
"tricycle",
"trilobite-101",
"tripod",
"t-shirt",
"tuning-fork",
"tweezer",
"umbrella-101",
"unicorn",
"vcr",
"video-projector",
"washing-machine",
"watch-101",
"waterfall",
"watermelon",
"welding-mask",
"wheelbarrow",
"windmill",
"wine-bottle",
"xylophone",
"yarmulke",
"yo-yo",
"zebra",
"airplanes-101",
"car-side-101",
"faces-easy-101",
"greyhound",
"tennis-shoes",
"toad",
"clutter",
]