OpenImages Setup with PostgreSQL
Uploading OpenImages into a PostgreSQL database, and querying for image URLs.{:.message}
OpenImages is a database of images that can be used to train and test machine learning and neural network object recognition algorithms. It has URLs of 9 million images with labeled objects, both by humans and object recognition software. While there are some instructions of how to download and organize the database in PostgreSQL, they are based on earlier datasets and there are mistakes. The following is an updated outline, as well as further instructions on how to query the database to retrieve images that match the needs of a project.
Download the Data
The current data can be downloaded by the following:
cd ~
mkdir openimages
cd openimages
wget "https://storage.googleapis.com/openimages/2017_07/images_2017_07.tar.gz"
wget "https://storage.googleapis.com/openimages/2017_07/annotations_human_bbox_2017_07.tar.gz"
wget "https://storage.googleapis.com/openimages/2017_07/annotations_human_2017_07.tar.gz"
wget "https://storage.googleapis.com/openimages/2017_07/annotations_machine_2017_07.tar.gz"
wget "https://storage.googleapis.com/openimages/2017_07/classes_2017_07.tar.gz"
Unfortunately, when you untar these files, they will all create the same folder 2017_07
. The following will keep the directories separate:
tar -xvzf images_2017_07.tar.gz
mv 2017_07 images_2017_07
tar -xvzf annotations_human_bbox_2017_07.tar.gz
mv 2017_07 annotations_human_bbox_2017_07
tar -xvzf annotations_human_2017_07.tar.gz
mv 2017_07 annotations_human_2017_07
tar -xvzf annotations_machine_2017_07.tar.gz
mv 2017_07 annotations_machine_2017_07
tar -xvzf classes_2017_07.tar.gz
mv 2017_07 classes_2017_07
rm *.tar.gz
In each of the folders annotations_human_2017_07
, annotations_human_bbox_2017_07
, annotations_machine_2017_07
, and images_2017_07
, there are three folders: test
, train
, and validation
. These three folders contain a list of images, including 1) the ImageID
(unique to that image), 2) the Source
of who identified the object (human or machine), 3) the LabelName
which is a unique identifier for each object (i.e. /m/0cmf2 is an Airplane), 4) and the Confidence
which is the probability of the label classification being correct.
Create the PostgreSQL Tables
After starting PostgreSQL from the terminal by the command psql
, the terminal should show the username and look something like:
andrew=#
A database can be created to contain the OpenImages database, which we’ll call openimages
by:
andrew=# CREATE DATABASE openimages;
If you enter \l
, you should see that the database openimages
now exists. You can connect to the database by:
andrew=# \c openimages
openimages=#
The terminal prompt should change to openimages=#
, which shows you are now in the openimages
database.
Next, create the tables. First, a table for the image metadata:
CREATE TABLE Images (
ImageID CHAR(16),
Subset VARCHAR,
OriginalURL VARCHAR,
OriginalLandingURL VARCHAR,
License VARCHAR,
AuthorProfileURL VARCHAR,
Author VARCHAR,
Title VARCHAR,
OriginalSize BIGINT,
OriginalMD5 VARCHAR,
Thumbnail300KURL VARCHAR,
PRIMARY KEY(ImageID)
);
A table for labels:
CREATE TABLE Labels (
ImageID CHAR(16) REFERENCES Images(ImageID),
Source VARCHAR,
LabelName VARCHAR REFERENCES Dict(LabelName),
Confidence REAL,
PRIMARY KEY(ImageID, Source, LabelName)
);
Finally, a table to map the LabelName
to a display name that is a description of the label:
CREATE TABLE Dict (
LabelName VARCHAR,
DisplayLabelName VARCHAR,
PRIMARY KEY (LabelName)
);
Uploading the Data
Upload the image metadata into the Images
table:
\COPY Images FROM 'images_2017_07/train/images.csv' DELIMITER ',' CSV HEADER;
\COPY Images FROM 'images_2017_07/validation/images.csv' DELIMITER ',' CSV HEADER;
Upload the image metadata into the Labels
table:
\COPY Labels FROM 'annotations_human_2017_07/train/annotations-human.csv' DELIMITER ',' CSV HEADER;
\COPY Labels FROM 'annotations_human_2017_07/test/annotations-human.csv' DELIMITER ',' CSV HEADER;
\COPY Labels FROM 'annotations_human_2017_07/validation/annotations-human.csv' DELIMITER ',' CSV HEADER;
\COPY Labels FROM 'annotations_machine_2017_07/train/annotations-machine.csv' DELIMITER ',' CSV HEADER;
\COPY Labels FROM 'annotations_machine_2017_07/test/annotations-machine.csv' DELIMITER ',' CSV HEADER;
\COPY Labels FROM 'annotations_machine_2017_07/validation/annotations-machine.csv' DELIMITER ',' CSV HEADER;
Upload the label name descriptions:
\COPY Dict FROM 'classes_2017_07/class-descriptions.csv' DELIMITER ',' CSV HEADER;
Query the Data
Let’s look at example data for each of the tables. First, let’s look at labels.
openimages=# SELECT * FROM Images LIMIT 5;
imageid | source | labelname | confidence
-----------------+--------+------------+------------
01b3e1bcccb2ba06 | human | /m/02jq33 | 0
01b3e1bcccb2ba06 | human | /m/02kvytt | 0
01b3e1bcccb2ba06 | human | /m/047fr | 0
01b3e1bcccb2ba06 | human | /m/09kxp | 1
01b3e1bcccb2ba06 | human | /m/0chlrk | 0
(5 rows)
However, let’s limit to positively identified objects by limiting to rows where the confidence is 1.
openimages=# SELECT * FROM Images WHERE Labels.Confidence = 1 LIMIT 5;
imageid | source | labelname | confidence
-----------------+--------+-----------+------------
34d98b4630321574 | human | /m/04f4xh | 1
34d98b4630321574 | human | /m/07yv9 | 1
34d98b4630321574 | human | /m/083wq | 1
34d98b4630321574 | human | /m/0k4j | 1
34d9993e9dae832c | human | /m/01d40f | 1
(5 rows)
Same for the label descriptions:
openimages=# SELECT * FROM Dict LIMIT 5;
labelname | displaylabelname
------------+---------------------
/m/0100nhbf | Sprengers tulip
/m/0104x9kv | Vinegret
/m/0105jzwx | Dabu-dabu
/m/0105ld7g | Pistachio ice cream
/m/0105lxy5 | Woku
(5 rows)
For the images, the rows are wide with many columns, so turn on the extended display to make it readable.
openimages=# \x on
openimages=# SELECT * FROM Images LIMIT 1;
-[ RECORD 1 ]------+----------------------------------------------------------------
imageid | 0001eeaf4aed83f9
subset | validation
originalurl | https://c2.staticflickr.com/6/5606/15611395595_f51465687d_o.jpg
originallandingurl | https://www.flickr.com/photos/hisgett/15611395595
license | https://creativecommons.org/licenses/by/2.0/
authorprofileurl | https://www.flickr.com/people/hisgett/
author | Tony Hisgett
title | American Airlines Boeing 777-323(ER) N717AN
originalsize | 2038323
originalmd5 | I4V4qq54NBEFDwBqPYCkDA==
thumbnail300kurl | https://c4.staticflickr.com/6/5606/15611395595_0594841ba5_z.jpg
openimages=# \x off
If we want to find a specific type of object, we can look for the label names that match the object. For example, if you want pictures of hands:
openimages=# SELECT * FROM dict WHERE DisplayLabelName LIKE 'Hand';
labelname | displaylabelname
----------+------------------
/m/0k65p | Hand
(1 row)
If we want things that include the word “hand”, we can use the %
operator:
openimages=# SELECT * FROM dict WHERE DisplayLabelName LIKE '%hand%' LIMIT 5;
labelname | displaylabelname
-----------+-------------------
/m/01613k | Holding hands
/m/026p7j9 | Beach handball
/m/027jy5t | Field handball
/m/02rqv26 | Bicycle handlebar
/m/02ws6z | Chandelier
(5 rows)
If we want it to start with “Hand”, don’t use %
at the beginning.
openimages=# SELECT * FROM Dict WHERE DisplayLabelName LIKE 'Hand%' LIMIT 5;
labelname | displaylabelname
----------+------------------
/m/016133 | Handshake
/m/016h1k | Handcuffs
/m/01nh1r | Handkerchief
/m/01w1x1 | Hand drum
/m/01yc83 | Hand tool
(5 rows)
Let’s say you want pictures that have hands, we can search for images with the LabelName
for “Hand” shown above (/m/0k65p).
openimages=# SELECT * FROM Labels WHERE LabelName='/m/0k65p' LIMIT 5;
imageid | source | labelname | confidence
-----------------+--------+-----------+------------
000a1249af2bc5f0 | human | /m/0k65p | 1
0010c714a5da358a | human | /m/0k65p | 0
00141571d986d241 | human | /m/0k65p | 1
001464cfae2a30b8 | human | /m/0k65p | 0
00146ba1e50ed8d8 | human | /m/0k65p | 1
(5 rows)
It would be better to get the actual URLS for the images (OriginalLandingURL
). To do this, we need to join the Images
with Labels
openimages=# SELECT originalurl FROM Labels
INNER JOIN Images ON Labels.ImageID = Images.ImageID
WHERE LabelName='/m/0k65p' LIMIT 5;
originalurl
-----------------------------------------------------------------
https://farm1.staticflickr.com/8087/8563450894_8f2fda7196_o.jpg
https://c3.staticflickr.com/4/3022/2623344128_4aaa8fc178_o.jpg
https://farm2.staticflickr.com/2603/3692981083_34b1710067_o.jpg
https://c1.staticflickr.com/9/8292/7859745110_b8c1401cd9_o.jpg
https://c1.staticflickr.com/8/7517/16104664631_c8bdf2a7ff_o.jpg
(5 rows)
The first URL is to the image:
So this database can be used to get a list of URLs of objects to use for training object recognition algorithms.