usage.md
Unicode text, UTF-8 text
What's this?
This is a platform for managing an image dataset. It's designed to make it easy for anyone to upload images, annotate them, and for people who need images to search for them. There's also a JSON API for automating tasks. It's also free software under the GNU AGPLv3.
Querying for pictures
The query format is based on YAML and used to query for pictures in the system.
Structure
The root can have 3 keys:
want
: A list of rules that the images must satisfy. If not provided, no filtering is done.exclude
: A list of rules that the images must not satisfy. If not provided, no filtering is done.include_obsolete
: If true the query may return images with a designated replacement. If false (default) this won't be possible.
want
and exclude
are lists of rules. Each rule is a dictionary with a single
key (this is to allow multiple rules of the same kind). Accepted rules are:
has: [object1, object2, ...]
: The image must contain any of the objects in the list, or a descendant of any of them.has_object: [object1, object2, ...]
: The image must contain any of the objects in the list.nature: [nature1, nature2, ...]
: The image must have one of the natures in the list. Natures are strings like "photo" that indicate the source of the image.licence: [licence1, licence2, ...]
: The image must have one of the licences in the list. If possible, licence IDs are SPDX identifiers, non-standard ones are prefixed withX-
.author: [author1, author2, ...]
: The image's author's username must be in the list.title: query
: Search for titles (ilike
).description: query
: Search for descriptions (ilike
).origin_url: query
: Search for origin URLs. The query matches the beginning of the URL excluding the protocol. (likecommons.wikimedia.org
)above_width: width
: The image must have a width greater than or equal to the given value, in pixels.above_height: height
: The image must have a height greater than or equal to the given value, in pixels.below_width: width
: The image must have a width less than or equal to the given value, in pixels.below_height: height
: The image must have a height less than or equal to the given value, in pixels.before_date: timestamp
: The image must have been uploaded before the given Unix timestamp.after_date: timestamp
: The image must have been uploaded after the given Unix timestamp.in_gallery: [gallery1, gallery2, ...]
: The image must be in any of the galleries (by ID) in the list.above_rating: rating
: The image must have a rating greater than or equal to the given value (1-5 stars). Images with no rating are included; useabove_rating_count: 1
to exclude them.below_rating: rating
: The image must have a rating less than or equal to the given value (1-5 stars).above_rating_count: count
: The image must have at least the given rating count.below_rating_count: count
: The image must have at most the given rating count.above_region_count: count
: The image must have at least the given number of regions.below_region_count: count
: The image must have at most the given number of regions.copied_from: [image1, image2, ...]
: The image must be a copy of an image in the images in the list (by ID).
ordering
, offset
and limit
can be specified as query parameters in the
URL. ordering
can be one of date-desc
, date-asc
, title-asc
, title-desc
,
number-regions-desc
, number-regions-asc
, random
. offset
and limit
are
integers that specify the number of images to skip and the maximum number of
images to return, respectively.
Example
# Restrictions for queried images want: # This means that the image must contain both rules, so both a cat and a dog - has_object: ["Cat (Felis catus)"] - has_object: ["Dog (Canis lupus familiaris)"] # Or we can put them in a list to mean that the image can contain any of the # objects in the list - has_object: ["Grass", "Flower"] # So the image must contain a cat and a dog, as well as either grass or # a flower # The following rule restricts the images to those with a certain source, # like a camera or a drawing; omitting this rule means that the images can # be of any source - nature: ["photo", "computer-3d-art"] # The following rule restricts the images to those with a certain licence - licence: ["CC-BY-1.0", "CC-BY-2.0", "CC-BY-3.0", "CC-BY-4.0", "CC0-1.0", "Unlicense", "WTFPL", "MIT", "BSD-2-Clause", "BSD-3-Clause", "Apache-2.0", "X-informal-attribution", "X-informal-do-anything", "X-public-domain-old", "X-public-domain"] # Prohibitions for queried images exclude: # This means that the image must not contain any of the objects in the list - has_object: ["Human"] # This excludes images uploaded before the given date - before_date: 1546300800 # This requires images to have a minimum resolution - below_width: 800 - below_height: 600 # In summary, we want images that contain both a cat and a dog, either a grass # or a flower, but not a human, taken after 2019-01-01, must be a photo or a # 3D render, must carry one of certain permissive licences and have a resolution # of at least 800x600 pixels.
You will get a list of JSON dictionaries with the following keys:
id
which is the picture's numeric ID.title
which is the picture's title.description
which is the picture's description.author
which is the picture's author's username.origin_url
which is the picture's origin URL.timestamp
which is the Unix time at which the picture was posted.width
andheight
which are the picture's dimensions, in pixels.file_format
which is the picture's MIME type.nature
which is the picture's nature.licences
which is a list of licence identifiers.replaces
which is the ID of the picture replaced by this one, if any.replaced_by
which is the ID of the picture's replacement, if any.regions
which represents the picture's annotations in the format described below.download
which is the URL of the image file.
If you query the endpoint /api/picture/<id>/
you will also get:
rating_average
which is the average rating of the picture from one to five stars.rating_count
which is the number of ratings of each grade.
This is done to avoid processing ratings when they aren't needed.
Raw annotation data format
The client sends raw data for image annotations in a JSON format which is a list of shapes. Each shape is a dictionary with the following keys:
type
: The type of the shape which can be:bbox
(bounding box, rectangle)polygon
polyline
point
shape
: The shape data. Its format depends on the shapetype
:For
bbox
it is a dictionary with keys x, y, w, h:{"x": x, "y": y, "w": w, "h": h}
For
polygon
andpolyline
it is a list of points; each point is a dictionary with keys x and y:[{"x": x1, "y": y1}, {"x": x2, "y": y2}, ...]
The only difference betweenpolygon
andpolyline
is that the former is supposed to be closed so the last point is connected to the first one.For
point
it is a dictionary with keys x and y:{"x": x, "y": y}
All coordinates are floating-point numbers in the range [0, 1] and relative to the image size, with the origin in the top-left corner.
object
: The ID of the type of object (label) depicted in the shape. This ID is a human-readable string that must be registered in the system before being used on shapes.
The server sends the same data back to the client, to use to show the existing annotations for an image.
Example
[ { "type": "bbox", "shape": {"x": 0.1, "y": 0.1, "w": 0.5, "h": 0.5}, "object": "Cat (Felis catus)" }, { "type": "polygon", "shape": [{"x": 0, "y": 0}, {"x": 1, "y": 0}, {"x": 0, "y": 1}], "object": "Slice of pizza margherita" }, { "type": "point", "shape": {"x": 0.5, "y": 0.5}, "object": "Cat (Felis catus) - left eye" } ]
Authenticating with the API
Your HTTP client must support cookies.
POST
to /api/login
with a JSON body containing keys username
and
password
.
POST
to /api/logout
to clear the session; you can also just delete the
cookie on your own.
User registration isn't supported by the API to prevent spam; use the HTML form.
Uploading from the API
You can upload pictures from the API if you're logged in. POST
to
/api/upload
with a form data containing a key json
with the value being a
JSON dictionary with title
, description
, origin_url
, licence
(list of
IDs), nature
(ID), and a file
file that is your image. The JSON can also
have a key annotations
if you want to prefill them — check above for the
format.
/api/picture/<id>/update
allows you to pass title
, description
,
origin_url
, licence_ids
and nature_id
in a JSON body to change an existing
picture.
Other endpoints
/api/licence/
provides a dictionary of the licences with the keys being the
ID and the value being another dictionary with keys title
, free
(whether
it respects the Four Freedoms) and pinned
which indicates if it is at the top
of the list.
/api/licence/<id>/
provides more details for the particular licence, including
id
, title
, description
, info_url
which links to a page with information
about the licence, legalese_url
which links to the actual legal text, free
,
pinned
and logo_url
.
/api/nature/
provides a dictionary of natures of the form id: description
.
/api/user/
provides information about users with the key being the name and
the value being a dictionary with the admin
boolean. It uses offset
and
limit
.
/api/user/<username>/
provides a dictionary with the user's id
, admin
status and joined
date.
POST
to /api/picture/<id>/rate
with a JSON body with a key rating
will
put a star rating on the picture. To delete the rating call it with a false
value.
/api/gallery/<id>
will give metadata about the gallery in JSON: id
, title
,
description
, owner
and users
. To get the pictures you can use a query.
POST
to /api/gallery/<id>/edit
with keys title
and description
in JSON
to update the gallery metadata.
POST
to /api/new-gallery
creates a new gallery with keys title
and
description
in the JSON.
POST
to /api/gallery/<id>/add-picture
with a JSON dictionary containing a
key picture_id
will add the picture. /api/gallery/<id>/add-picture
will do
the reverse.
POST
to /api/gallery/<id>/users/add
with a JSON dictionary containing a key
username
will trust an user, /api/gallery/<id>/users/remove
will do the
reverse.
1What's this? 2------------ 3 4This is a platform for managing an image dataset. It's designed to make it easy 5for anyone to upload images, annotate them, and for people who need images to 6search for them. There's also a JSON API for automating tasks. It's also free 7software under the GNU AGPLv3. 8 9Querying for pictures 10--------------------- 11 12The query format is based on YAML and used to query for pictures in the system. 13 14### Structure 15The root can have 3 keys: 16* `want`: A list of rules that the images must satisfy. If not provided, no 17filtering is done. 18* `exclude`: A list of rules that the images must not satisfy. If not provided, 19no filtering is done. 20* `include_obsolete`: If true the query may return images with a designated 21replacement. If false (default) this won't be possible. 22 23`want` and `exclude` are lists of rules. Each rule is a dictionary with a single 24key (this is to allow multiple rules of the same kind). Accepted rules are: 25* `has: [object1, object2, ...]`: The image must contain any of the objects in 26the list, or a descendant of any of them. 27* `has_object: [object1, object2, ...]`: The image must contain any of the 28objects in the list. 29* `nature: [nature1, nature2, ...]`: The image must have one of the natures in 30the list. Natures are strings like "photo" that indicate the source of the 31image. 32* `licence: [licence1, licence2, ...]`: The image must have one of the licences 33in the list. If possible, licence IDs are SPDX identifiers, non-standard ones 34are prefixed with `X-`. 35* `author: [author1, author2, ...]`: The image's author's username must be in 36the list. 37* `title: query`: Search for titles (`ilike`). 38* `description: query`: Search for descriptions (`ilike`). 39* `origin_url: query`: Search for origin URLs. The query matches the beginning 40of the URL excluding the protocol. (like `commons.wikimedia.org`) 41* `above_width: width`: The image must have a width greater than or equal to 42the given value, in pixels. 43* `above_height: height`: The image must have a height greater than or equal to 44the given value, in pixels. 45* `below_width: width`: The image must have a width less than or equal to the 46given value, in pixels. 47* `below_height: height`: The image must have a height less than or equal to the 48given value, in pixels. 49* `before_date: timestamp`: The image must have been uploaded before the given 50Unix timestamp. 51* `after_date: timestamp`: The image must have been uploaded after the given 52Unix timestamp. 53* `in_gallery: [gallery1, gallery2, ...]`: The image must be in any of the 54galleries (by ID) in the list. 55* `above_rating: rating`: The image must have a rating greater than or equal to 56the given value (1-5 stars). Images with no rating are included; use 57`above_rating_count: 1` to exclude them. 58* `below_rating: rating`: The image must have a rating less than or equal to the 59given value (1-5 stars). 60* `above_rating_count: count`: The image must have at least the given rating 61count. 62* `below_rating_count: count`: The image must have at most the given rating 63count. 64* `above_region_count: count`: The image must have at least the given number of 65regions. 66* `below_region_count: count`: The image must have at most the given number of 67regions. 68* `copied_from: [image1, image2, ...]`: The image must be a copy of an image in the 69images in the list (by ID). 70 71`ordering`, `offset` and `limit` can be specified as query parameters in the 72URL. `ordering` can be one of `date-desc`, `date-asc`, `title-asc`, `title-desc`, 73`number-regions-desc`, `number-regions-asc`, `random`. `offset` and `limit` are 74integers that specify the number of images to skip and the maximum number of 75images to return, respectively. 76 77### Example 78~~~yaml 79# Restrictions for queried images 80want: 81# This means that the image must contain both rules, so both a cat and a dog 82- has_object: ["Cat (Felis catus)"] 83- has_object: ["Dog (Canis lupus familiaris)"] 84# Or we can put them in a list to mean that the image can contain any of the 85# objects in the list 86- has_object: ["Grass", "Flower"] 87# So the image must contain a cat and a dog, as well as either grass or 88# a flower 89# The following rule restricts the images to those with a certain source, 90# like a camera or a drawing; omitting this rule means that the images can 91# be of any source 92- nature: ["photo", "computer-3d-art"] 93# The following rule restricts the images to those with a certain licence 94- licence: ["CC-BY-1.0", "CC-BY-2.0", "CC-BY-3.0", "CC-BY-4.0", "CC0-1.0", 95"Unlicense", "WTFPL", "MIT", "BSD-2-Clause", "BSD-3-Clause", 96"Apache-2.0", "X-informal-attribution", "X-informal-do-anything", 97"X-public-domain-old", "X-public-domain"] 98# Prohibitions for queried images 99exclude: 100# This means that the image must not contain any of the objects in the list 101- has_object: ["Human"] 102# This excludes images uploaded before the given date 103- before_date: 1546300800 104# This requires images to have a minimum resolution 105- below_width: 800 106- below_height: 600 107# In summary, we want images that contain both a cat and a dog, either a grass 108# or a flower, but not a human, taken after 2019-01-01, must be a photo or a 109# 3D render, must carry one of certain permissive licences and have a resolution 110# of at least 800x600 pixels. 111~~~ 112 113You will get a list of JSON dictionaries with the following keys: 114 115* `id` which is the picture's numeric ID. 116* `title` which is the picture's title. 117* `description` which is the picture's description. 118* `author` which is the picture's author's username. 119* `origin_url` which is the picture's origin URL. 120* `timestamp` which is the Unix time at which the picture was posted. 121* `width` and `height` which are the picture's dimensions, in pixels. 122* `file_format` which is the picture's MIME type. 123* `nature` which is the picture's nature. 124* `licences` which is a list of licence identifiers. 125* `replaces` which is the ID of the picture replaced by this one, if any. 126* `replaced_by` which is the ID of the picture's replacement, if any. 127* `regions` which represents the picture's annotations in the format described 128below. 129* `download` which is the URL of the image file. 130 131If you query the endpoint `/api/picture/<id>/` you will also get: 132 133* `rating_average` which is the average rating of the picture from one to five 134stars. 135* `rating_count` which is the number of ratings of each grade. 136 137This is done to avoid processing ratings when they aren't needed. 138 139Raw annotation data format 140-------------------------- 141 142The client sends raw data for image annotations in a JSON format which is a list 143of shapes. Each shape is a dictionary with the following keys: 144 145* `type`: The type of the shape which can be: 146* `bbox` (bounding box, rectangle) 147* `polygon` 148* `polyline` 149* `point` 150* `shape`: The shape data. Its format depends on the shape `type`: 151* For `bbox` it is a dictionary with keys x, y, w, h: 152` 153{"x": x, "y": y, "w": w, "h": h} 154` 155* For `polygon` and `polyline` it is a list of points; each point is a 156dictionary with keys x and y: 157` 158[{"x": x1, "y": y1}, {"x": x2, "y": y2}, ...] 159` 160The only difference between `polygon` and `polyline` is that the former is 161supposed to be closed so the last point is connected to the first one. 162* For `point` it is a dictionary with keys x and y: 163` 164{"x": x, "y": y} 165` 166* All coordinates are floating-point numbers in the range [0, 1] and relative 167to the image size, with the origin in the top-left corner. 168* `object`: The ID of the type of object (label) depicted in the shape. This ID 169is a human-readable string that must be registered in the system before 170being used on shapes. 171 172The server sends the same data back to the client, to use to show the existing 173annotations for an image. 174 175### Example 176 177~~~json 178[ 179{ 180"type": "bbox", 181"shape": {"x": 0.1, "y": 0.1, "w": 0.5, "h": 0.5}, 182"object": "Cat (Felis catus)" 183}, 184{ 185"type": "polygon", 186"shape": [{"x": 0, "y": 0}, {"x": 1, "y": 0}, {"x": 0, "y": 1}], 187"object": "Slice of pizza margherita" 188}, 189{ 190"type": "point", 191"shape": {"x": 0.5, "y": 0.5}, 192"object": "Cat (Felis catus) - left eye" 193} 194] 195~~~ 196 197Authenticating with the API 198--------------------------- 199 200Your HTTP client must support cookies. 201 202`POST` to `/api/login` with a JSON body containing keys `username` and 203`password`. 204 205`POST` to `/api/logout` to clear the session; you can also just delete the 206cookie on your own. 207 208User registration isn't supported by the API to prevent spam; use the HTML form. 209 210Uploading from the API 211---------------------- 212 213You can upload pictures from the API if you're logged in. `POST` to 214`/api/upload` with a form data containing a key `json` with the value being a 215JSON dictionary with `title`, `description`, `origin_url`, `licence` (list of 216IDs), `nature` (ID), and a `file` file that is your image. The JSON can also 217have a key `annotations` if you want to prefill them — check above for the 218format. 219 220`/api/picture/<id>/update` allows you to pass `title`, `description`, 221`origin_url`, `licence_ids` and `nature_id` in a JSON body to change an existing 222picture. 223 224Other endpoints 225--------------- 226 227`/api/licence/` provides a dictionary of the licences with the keys being the 228ID and the value being another dictionary with keys `title`, `free` (whether 229it respects the Four Freedoms) and `pinned` which indicates if it is at the top 230of the list. 231 232`/api/licence/<id>/` provides more details for the particular licence, including 233`id`, `title`, `description`, `info_url` which links to a page with information 234about the licence, `legalese_url` which links to the actual legal text, `free`, 235`pinned` and `logo_url`. 236 237`/api/nature/` provides a dictionary of natures of the form `id: description`. 238 239`/api/user/` provides information about users with the key being the name and 240the value being a dictionary with the `admin` boolean. It uses `offset` and 241`limit`. 242 243`/api/user/<username>/` provides a dictionary with the user's `id`, `admin` 244status and `joined` date. 245 246`POST` to `/api/picture/<id>/rate` with a JSON body with a key `rating` will 247put a star rating on the picture. To delete the rating call it with a false 248value. 249 250`/api/gallery/<id>` will give metadata about the gallery in JSON: `id`, `title`, 251`description`, `owner` and `users`. To get the pictures you can use a query. 252 253`POST` to `/api/gallery/<id>/edit` with keys `title` and `description` in JSON 254to update the gallery metadata. 255 256`POST` to `/api/new-gallery` creates a new gallery with keys `title` and 257`description` in the JSON. 258 259`POST` to `/api/gallery/<id>/add-picture` with a JSON dictionary containing a 260key `picture_id` will add the picture. `/api/gallery/<id>/add-picture` will do 261the reverse. 262 263`POST` to `/api/gallery/<id>/users/add` with a JSON dictionary containing a key 264`username` will trust an user, `/api/gallery/<id>/users/remove` will do the 265reverse. 266