Skip to content

Commit 935242f

Browse files
jpuigcervercopybara-github
authored andcommitted
Add the 2017 INaturalist Competition dataset.
PiperOrigin-RevId: 282831191
1 parent 983cdb8 commit 935242f

File tree

11 files changed

+5344
-0
lines changed

11 files changed

+5344
-0
lines changed

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@
9696
'image/food-101_classes.txt',
9797
'image/imagenet2012_labels.txt',
9898
'image/imagenet2012_validation_labels.txt',
99+
'image/inaturalist_labels.txt',
100+
'image/inaturalist_supercategories.txt',
99101
'image/open_images_classes_all.txt',
100102
'image/open_images_classes_boxable.txt',
101103
'image/open_images_classes_trainable.txt',

tensorflow_datasets/image/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
from tensorflow_datasets.image.imagenet import Imagenet2012
5656
from tensorflow_datasets.image.imagenet2012_corrupted import Imagenet2012Corrupted
5757
from tensorflow_datasets.image.imagenet_resized import ImagenetResized
58+
from tensorflow_datasets.image.inaturalist import INaturalist2017
5859
from tensorflow_datasets.image.lfw import LFW
5960
from tensorflow_datasets.image.lost_and_found import LostAndFound
6061
from tensorflow_datasets.image.lsun import Lsun
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# coding=utf-8
2+
# Copyright 2019 The TensorFlow Datasets Authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Lint as: python3
17+
"""INaturalist datasets."""
18+
19+
from __future__ import absolute_import
20+
from __future__ import division
21+
from __future__ import print_function
22+
23+
import json
24+
import os
25+
26+
import six.moves.urllib as urllib
27+
import tensorflow as tf
28+
import tensorflow_datasets.public_api as tfds
29+
30+
_DESCRIPTION = """\
31+
This dataset contains a total of 5,089 categories, across 579,184 training
32+
images and 95,986 validation images. For the training set, the distribution of
33+
images per category follows the observation frequency of that category by the
34+
iNaturalist community.
35+
36+
Although the original dataset contains some images with bounding boxes,
37+
currently, only image-level annotations are provided (single label/image).
38+
In addition, the organizers have not published the test labels, so we only
39+
provide the test images (label = -1).
40+
"""
41+
_CITATION = """\
42+
@InProceedings{Horn_2018_CVPR,
43+
author = {
44+
Van Horn, Grant and Mac Aodha, Oisin and Song, Yang and Cui, Yin and Sun, Chen
45+
and Shepard, Alex and Adam, Hartwig and Perona, Pietro and Belongie, Serge},
46+
title = {The INaturalist Species Classification and Detection Dataset},
47+
booktitle = {
48+
The IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
49+
month = {June},
50+
year = {2018}
51+
}
52+
"""
53+
_URL = "http://www.vision.caltech.edu/~gvanhorn/datasets/inaturalist/fgvc4_competition/"
54+
55+
56+
class INaturalist2017(tfds.core.GeneratorBasedBuilder):
57+
"""Dataset from the INaturalist Competition 2017."""
58+
59+
VERSION = tfds.core.Version("0.1.0")
60+
61+
def _info(self):
62+
"""Define the dataset info."""
63+
return tfds.core.DatasetInfo(
64+
builder=self,
65+
description=_DESCRIPTION,
66+
features=tfds.features.FeaturesDict({
67+
"id": tfds.features.Text(),
68+
"image": tfds.features.Image(),
69+
"label": tfds.features.ClassLabel(
70+
names_file=tfds.core.get_tfds_path(
71+
os.path.join("image", "inaturalist_labels.txt"))),
72+
"supercategory": tfds.features.ClassLabel(
73+
names_file=tfds.core.get_tfds_path(
74+
os.path.join("image", "inaturalist_supercategories.txt"))),
75+
}),
76+
supervised_keys=("image", "label"),
77+
homepage="https://github.com/visipedia/inat_comp/tree/master/2017",
78+
citation=_CITATION)
79+
80+
def _split_generators(self, dl_manager):
81+
output_files = dl_manager.download_and_extract({
82+
"trainval_images":
83+
tfds.download.Resource(
84+
url=urllib.parse.urljoin(_URL, "train_val_images.tar.gz"),
85+
extract_method=tfds.download.ExtractMethod.NO_EXTRACT),
86+
"trainval_annos":
87+
urllib.parse.urljoin(_URL, "train_val2017.zip"),
88+
"test_images":
89+
tfds.download.Resource(
90+
url=urllib.parse.urljoin(_URL, "test2017.tar.gz"),
91+
extract_method=tfds.download.ExtractMethod.NO_EXTRACT),
92+
93+
})
94+
return [
95+
tfds.core.SplitGenerator(
96+
name=tfds.Split.TRAIN,
97+
gen_kwargs=dict(
98+
images_archive=dl_manager.iter_archive(
99+
output_files["trainval_images"]),
100+
annon_file=os.path.join(output_files["trainval_annos"],
101+
"train2017.json"),
102+
),
103+
),
104+
tfds.core.SplitGenerator(
105+
name=tfds.Split.VALIDATION,
106+
gen_kwargs=dict(
107+
images_archive=dl_manager.iter_archive(
108+
output_files["trainval_images"]),
109+
annon_file=os.path.join(output_files["trainval_annos"],
110+
"val2017.json"),
111+
),
112+
),
113+
tfds.core.SplitGenerator(
114+
name=tfds.Split.TEST,
115+
gen_kwargs=dict(
116+
images_archive=dl_manager.iter_archive(
117+
output_files["test_images"]),
118+
annon_file=None,
119+
),
120+
),
121+
]
122+
123+
def _generate_examples(self, images_archive, annon_file):
124+
"""Generate examples."""
125+
if annon_file is not None:
126+
# Training and validation images.
127+
with tf.io.gfile.GFile(annon_file, "r") as f:
128+
data = json.load(f)
129+
# First read the annotations file, used to filter the contents of the
130+
# tar.gz file when yielding examples.
131+
key2data = {}
132+
for image, annotation in zip(data["images"], data["annotations"]):
133+
category_id = annotation["category_id"]
134+
category = data["categories"][category_id]["name"]
135+
supercategory = data["categories"][category_id]["supercategory"]
136+
key = os.path.basename(image["file_name"]).split(".")[0]
137+
key2data[key] = {
138+
"id": key,
139+
"label": category,
140+
"supercategory": supercategory,
141+
}
142+
# Read tar.gz file containing train & validation images and yield relevant
143+
# examples.
144+
for fpath, fobj in images_archive:
145+
key = os.path.basename(fpath).split(".")[0]
146+
if key in key2data:
147+
data = key2data[key].copy()
148+
data["image"] = fobj
149+
yield key, data
150+
else:
151+
# Read tar.gz file containing all test images and yield all examples.
152+
for fpath, fobj in images_archive:
153+
key = os.path.basename(fpath).split(".")[0]
154+
# Note: test labels are not annotated, so just return -1 as labels.
155+
yield key, {
156+
"id": key,
157+
"image": fobj,
158+
"label": -1,
159+
"supercategory": -1,
160+
}

0 commit comments

Comments
 (0)