Skip to content
/ Exact Public
forked from DeepMicroscopy/Exact

An open source online platform for collaborative image labeling of almost everything

License

Notifications You must be signed in to change notification settings

JXuann/Exact

 
 

Repository files navigation

Exact

This is a collaborative online tool for labeling image data.

ScreenShot

Reference

This paper describes the EXACT-Server in depth. Please cite if you use this tool in your research:

Marzahl et al. EXACT: A collaboration toolset for algorithm-aided annotation of almost everything

@misc{marzahl2020exact,
    title={EXACT: A collaboration toolset for algorithm-aided annotation of almost everything},
    author={Christian Marzahl and Marc Aubreville and Christof A. Bertram and Jennifer Maier and Christian Bergler and Christine Kröger and Jörn Voigt and Robert Klopfleisch and Andreas Maier},
    year={2020},
    eprint={2004.14595},
    archivePrefix={arXiv},
    primaryClass={cs.HC}
}

Features

  • Sync with the offline Tool SlideRunner
  • team creation
  • upload image sets in the multiple formats like: whole slide image (WSI) formats or .png, .jpg, .jepg, .bmp etc.
  • bounding box, circle and polygon support
  • export format creation
  • label export
  • image preloading for labeling and verification
  • label verification
  • upload of existing labels
  • WSI viewer

Documentation

Describtion Video
Explains how teams, products and annotation types are created Datasets
Describes how to create, view and edit image sets and upload images. Datasets
Describes basic viewer and plugin functions. Datasets
Explains collaboratory annotation features Datasets
Shows multiple types of datasets Datasets
Explains the screening plugin for WSI Datasets
Syncronisation with the offline tool SlideRunner Datasets
Advanced polygon annotation operations Datasets
REST-API Example pip install EXCAT-Sync
Code
Notebook

Install

Docker

Install Docker

Checkout the latest release:

git clone https://github.com/ChristianMarzahl/Exact.git

Development

Copy and rename settings.py.example to settings.py in the exact folder.

Modify the configuration files: env.dev and env.dev.db or use the default configuration.

Build and run the container:

docker-compose -f docker-compose.yml up -d --build
docker-compose logs -f 

Navigate to http://localhost:8000/ For default the super user login is:

User: exact
Pw: exact

Production

Additional features:

  • gunicorn
  • nginx

Copy the files env.dev and env.dev.db, rename to env.prod and env.prod.db and change settings according to your preferences.

Copy and rename settings.py.example to settings.py in the exact folder.

Build and run the container:


docker-compose -f docker-compose.prod.yml up -d --build
docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput 
docker-compose -f docker-compose.prod.yml exec web python manage.py createsuperuser
docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input --clear
docker-compose -f docker-compose.prod.yml logs -f

Navigate to http://localhost:1337/

Cloud

To use cloud services like amazon fargate. The exact server has to connect to a cloud database like amazon rds.

Copy the files env.dev and env.dev.db, rename to env.prod and env.prod.aws-db and change settings according to your preferences.

Copy and rename settings.py.example to settings.py in the exact folder.

Build and run the container:

docker-compose -f docker-compose.prod.aws-db.yml down -v --remove-orphans
docker-compose -f docker-compose.prod.aws-db.yml up -d --build
docker-compose -f docker-compose.prod.aws-db.yml exec web python manage.py migrate --noinput
docker-compose -f docker-compose.prod.aws-db.yml exec web python manage.py createsuperuser
docker-compose -f docker-compose.prod.aws-db.yml exec web python manage.py collectstatic --no-input --clear
docker-compose -f docker-compose.prod.aws-db.yml logs -f

Send container to AWS ECR

Invoke-Expression -Command (aws ecr get-login --no-include-email)

docker tag exact_nginx:latest **************.dkr.ecr.eu-central-1.amazonaws.com/exact_nginx:latest
docker tag exact_web:latest **************.dkr.ecr.eu-central-1.amazonaws.com/exact:latest

docker push **************.dkr.ecr.eu-central-1.amazonaws.com/exact_nginx:latest
docker push **************.dkr.ecr.eu-central-1.amazonaws.com/exact:latest

Windows

The Server is also runnig on Windows but I would recommend to use docker in that case.

MacOS or Linux

Install libvips and verify by executing the comand vips:

https://libvips.github.io/libvips/
[Ubuntu](https://github.com/libvips/libvips/wiki/Build-for-Ubuntu)

Checkout the latest release:

git clone https://github.com/ChristianMarzahl/Exact.git

In our production Senty is used for error reporting (pip install raven). django-auth-ldap is used for login via ldap uwsgi is used to serve the app to nginx

Install Python Dependencies:

pip3 install -r requirements.txt

Copy settings.py.example to settings.py in the exact folder:

cp exact/exact/settings.py.example exact/exact/settings.py

and customize the settings.py.

The following settings should probably be changed:

  • The secret key
  • The DEBUG setting
  • The ALLOWED_HOSTS
  • The database settings
  • The UPLOAD_FS_GROUP to the id of the group that should access and create the uploaded images

For the database, postgresql is used. Install it by running sudo apt install postgresql

Initialize the database cluster with sudo -iu postgres initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'.

Note: It may be that initdb is not in your current PATH (seems to be default for postgresql >= 10), in this case, you have to specify the proper path to initdb, e.g: sudo -iu postgres /usr/lib/postgresql/*/bin/initdb --locale en_US.UTF-8 -D '/var/lib/postgresql/data' (for Ubuntu systems)

To start the postgresql server, run sudo systemctl start postgresql.service. If the server should always be started on boot, run sudo systemctl enable postgresql.service.

Then, create the user and the database by running

sudo -iu postgres psql

and then, in the postgres environment

CREATE USER exact PASSWORD 'exact';
CREATE DATABASE exact WITH OWNER exact ENCODING UTF8;

where of course the password and the user should be adapted to the ones specified in the database settings in the settings.py.

To initialize the database, run ./manage.py migrate

To create an administrator user, run ./manage.py createsuperuser.

./manage.py runserver starts the server with the configuration given in the settings.py file.

To create annotation types, log into the application and click on Administration at the very bottom of the home page.

For production systems it is necessary to run the following commands after each upgrade

./manage.py migrate
./manage.py compilemessages
./manage.py collectstatic

Our production uwisgi config is

[uwsgi]
socket = /tmp/exact.socket
chmod-socket = 666
chdir = /srv/exact/Exact/exact/
master = true
binary-path = /usr/bin/uwsgi
virtualenv = /srv/exact/virtualenv/exact
module = exact.wsgi
uid = exact
gid = exact
processes = 6
#async = 10
threads = 1
#logto = /var/log/exact.log
plugins = python3,logfile
logger = file:/var/log/exact.log


Example Nginx Config:

upstream exact {
    server web:8000;
}

server {

    listen 80;

    client_max_body_size 10000M;
    keepalive_timeout 65;

    proxy_connect_timeout       6000s;
    proxy_send_timeout          6000s;
    proxy_read_timeout          6000s;
    send_timeout                6000s;
    client_body_timeout     6000s;

    location / {
        proxy_pass http://exact;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
	
	location /static/ {
        expires 1h;
        alias /home/app/web/static/;
    }
	
	
    location /media/ {
        expires 1h;
        alias /home/app/web/media/;
    }

}

Upgrade

pip install -U -r requirements.txt
./manage.py migrate

for additional steps on some releases see instructions in UPGRADE.md

If you want to provide zip files of image sets, set ENABLE_ZIP_DOWNLOAD = True in your settings.py. A daemon that creates and updates the zip files is necessary, you can start it with ./manage.py runzipdaemon. Please take into account that the presence of zip files will double your storage requirement.

Zip archive download via a script is also possible. The URL is /images/imageset/<id>/download/. A successful request returns HTTP 200 OK and the zip file. When the file generation is still in progress, HTTP 202 ACCEPTED is returned. For an empty image set, HTTP 204 NO CONTENT is returned instead of an empty zip archive.

REST-API

OpenAPI-Schema

GET /api/v1/openapi

Examples

https://github.com/rsinger86/drf-flex-fields
https://django-filter.readthedocs.io/en/master/

Token

$ curl -X POST -d '{"username": "exact","password": "top_secret"}' -H
'Content-Type: application/json'  http://127.0.0.1:8000/api/auth/token/login/

All suported classes

GET /api/v1/

{
    "users/users": "http://127.0.0.1:8000/api/v1/users/users/",
    "users/teams": "http://127.0.0.1:8000/api/v1/users/teams/",
    "users/team_membership": "http://127.0.0.1:8000/api/v1/users/team_membership/",
    "images/images": "http://127.0.0.1:8000/api/v1/images/images/",
    "images/image_sets": "http://127.0.0.1:8000/api/v1/images/image_sets/",
    "images/set_tags": "http://127.0.0.1:8000/api/v1/images/set_tags/",
    "images/screening_modes": "http://127.0.0.1:8000/api/v1/images/screening_modes/",
    "annotations/annotations": "http://127.0.0.1:8000/api/v1/annotations/annotations/",
    "annotations/annotation_types": "http://127.0.0.1:8000/api/v1/annotations/annotation_types/",
    "annotations/annotation_media_files": "http://127.0.0.1:8000/api/v1/annotations/annotation_media_files/",
    "annotations/verifications": "http://127.0.0.1:8000/api/v1/annotations/verifications/",
    "annotations/log_image_actions": "http://127.0.0.1:8000/api/v1/annotations/log_image_actions/",
    "administration/products": "http://127.0.0.1:8000/api/v1/administration/products/"
}

Filter all image_sets with "Katze" in name and expand products and main_annotation_type

GET /api/v1/images/image_sets/?name__contains=Katze&expand=product_set,main_annotation_type

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 3,
            "name": "EIPH-Katze",
            "path": "exact_1_3",
            "location": null,
            "description": "",
            "images": [
                17,
                20,
                22,
                23,
                26,
                27,
                30
            ],
            "product_set": [
                {
                    "id": 2,
                    "name": "EIPH",
                    "description": "",
                    "team": 1,
                    "creator": 1,
                    "imagesets": [
                        2,
                        3,
                        16
                    ],
                    "annotationtype_set": [
                        10,
                        11,
                        12,
                        13,
                        14
                    ]
                }
            ],
            "main_annotation_type": {
                "id": 10,
                "name": "0",
                "vector_type": 1,
                "node_count": 0,
                "enable_concealed": false,
                "enable_blurred": false,
                "color_code": "#0000FF",
                "default_width": 120,
                "default_height": 120,
                "sort_order": 0,
                "closed": true,
                "area_hit_test": true,
                "product": 2
            },
            "set_tags": [],
            "team": 1,
            "creator": 1
        }
    ]
}

Include(fields) or Exclude(omit) fields

GET /api/v1/images/image_sets/?name__contains=Katze&fields=name

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "name": "EIPH-Katze"
        }
    ]
}
GET /api/v1/images/image_sets/?name__contains=Katze&omit=images,product_set

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 3,
            "name": "EIPH-Katze",
            "path": "exact_1_3",
            "location": null,
            "description": "",
            "main_annotation_type": 10,
            "set_tags": [],
            "team": 1,
            "creator": 1
        }
    ]
}

Used dependencies

The exact relies on the following plugins, libraries and frameworks:

Name Version License
Django 3.0 BSD
Pillow 5.4.1 Standard PIL License
asgiref 3.2.3 BSD
confusable-homoglyphs 3.2.0 MIT
django-friendly-tag-loader 1.3.1 MIT
django-registration 3.0.1 MIT
django-widget-tweaks 1.4.3 MIT license
djangorestframework 3.11.0 BSD
fasteners 0.14.1 ASL 2.0
gunicorn 19.9.0 MIT
imagecodecs-lite 2019.12.3 BSD
monotonic 1.5 Apache
numpy 1.17.4 BSD
opencv-python 4.1.2.30 MIT
openslide-python 1.1.1 GNU Lesser General Public License, version 2.1
psycopg2-binary 2.7.7 LGPL with exceptions or ZPL
pytz 2018.9 MIT
six 1.12.0 MIT
sqlparse 0.3.0 BSD
tifffile 2019.7.26.2 BSD
Bootstrap 4.4 BSD
jQuery 3.4.1 MIT
jQuery-Autocomplete 1.4.1
jQuery-File-Upload 10.7.0 MIT
OpenSeadragon 2.4.1 BSD-3

We are grateful to the maintainers and contributors of the respective projects.

ImageTagger Reference

This paper describes the Bit-Bots imagetagger we build on in depth. Please cite if you use this tool in your research:

FIEDLER, Niklas, et al. imagetagger: An Open Source Online Platform for Collaborative Image Labeling. In: RoboCup 2018: Robot World Cup XXII. Springer, 2018.

@inproceedings{imagetagger2018,
   author={Fiedler, Niklas and Bestmann, Marc and Hendrich, Norman},
   year={2018},
   title={Imagetagger: An Open Source Online Platform for Collaborative Image Labeling},
   booktitle={RoboCup 2018: Robot World Cup XXII},
   organization={Springer}
}

About

An open source online platform for collaborative image labeling of almost everything

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 50.0%
  • Python 25.5%
  • HTML 23.5%
  • Other 1.0%