Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [Task](#task)
- [Image](#image)
- [Image Classification](#image-classification)
- [Multi Image Classification](#multi-image-classification)
- [Sequential Image](#sequential-image)
- [Video](#video)
- [Video Classification](#video-classification)
Expand Down Expand Up @@ -560,6 +561,129 @@ Example of a single image classification task object
}
```

### Multi Image Classification

Supported following project types:

- Multi Image - Classification

#### Create Task

Create a new task.

```python
task = client.create_multi_image_classification_task(
project="YOUR_PROJECT_SLUG",
name="sample",
folder_path="./sample",
priority=10, # (optional) none: 0, low: 10, medium: 20, high: 30
attributes=[
{
"type": "text",
"key": "attribute-key",
"value": "attribute-value"
}
]
)
```

##### Limitation


- You can upload up to a size of 20 MB.
- You can upload up to a total size of 2 GB.
- You can upload up to 6 files in total.

#### Find Task

Find a single task.

```python
task = client.find_multi_image_classification_task(task_id="YOUR_TASK_ID")
```

Find a single task by name.

```python
tasks = client.find_multi_image_classification_task_by_name(project="YOUR_PROJECT_SLUG", task_name="YOUR_TASK_NAME")
```

#### Get Tasks

Get tasks.

```python
tasks = client.get_multi_image_classification_tasks(project="YOUR_PROJECT_SLUG")
```

#### Update Task

Update a single task.

```python
task_id = client.update_multi_image_classification_task(
task_id="YOUR_TASK_ID",
status="approved",
assignee="USER_SLUG",
tags=["tag1", "tag2"],
priority=10, # (optional) none: 0, low: 10, medium: 20, high: 30
attributes=[
{
"type": "text",
"key": "attribute-key",
"value": "attribute-value"
}
]
)
```

#### Response

Example of a single task object

```python
{
"id": "YOUR_TASK_ID",
"name": "sample",
"contents": [
{
"name": "content-name-1",
"url": "content-url-1",
"width": 100,
"height": 100,
},
{
"name": "content-name-2",
"url": "content-url-2",
"width": 100,
"height": 100,
}
],
"status": "registered",
"externalStatus": "registered",
"priority": 10,
"tags": [],
"assignee": "ASSIGNEE_NAME",
"reviewer": "REVIEWER_NAME",
"externalAssignee": "EXTERNAL_ASSIGNEE_NAME",
"externalReviewer": "EXTERNAL_REVIEWER_NAME",
"attributes": [
{
"type": "text",
"key": "attribute-key-1",
"value": "attribute-value-1"
},
{
"type": "text",
"key": "attribute-key-2",
"value": "attribute-value-2"
}
],
"createdAt": "2021-02-22T11:25:27.158Z",
"updatedAt": "2021-02-22T11:25:27.158Z"
}
```

### Sequential Image

Supported following project types:
Expand Down
203 changes: 203 additions & 0 deletions fastlabel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,29 @@ def find_image_classification_task(self, task_id: str) -> dict:
"""
endpoint = "tasks/image/classification/" + task_id
return self.api.get_request(endpoint)

def find_multi_image_classification_task(self, task_id: str) -> dict:
"""
Find a single multi image classification task.
"""
endpoint = "tasks/multi-image/classification/" + task_id
return self.api.get_request(endpoint)

def find_multi_image_classification_task_by_name(
self, project: str, task_name: str
) -> dict:
"""
Find a single multi image classification task by name.

project is slug of your project (Required).
task_name is a task name (Required).
"""
tasks = self.get_multi_image_classification_tasks(
project=project, task_name=task_name
)
if not tasks:
return None
return tasks[0]

def find_image_classification_task_by_name(
self, project: str, task_name: str
Expand Down Expand Up @@ -409,6 +432,46 @@ def get_image_classification_tasks(
if limit:
params["limit"] = limit
return self.api.get_request(endpoint, params=params)

def get_multi_image_classification_tasks(
self,
project: str,
status: str = None,
external_status: str = None,
tags: list = [],
task_name: str = None,
offset: int = None,
limit: int = 100,
) -> list:
"""
Returns a list of multi image classification tasks.
Returns up to 1000 at a time, to get more,
set offset as the starting position to fetch.

project is slug of your project (Required).
status can be 'registered', 'completed', 'skipped', 'reviewed', 'sent_back',
'approved', 'declined' (Optional).
external_status can be 'registered', 'completed', 'skipped', 'reviewed',
'sent_back', 'approved', 'declined', 'customer_declined' (Optional).
tags is a list of tag (Optional).
offset is the starting position number to fetch (Optional).
limit is the max number to fetch (Optional).
"""
endpoint = "tasks/multi-image/classification"
params = {"project": project}
if status:
params["status"] = status
if external_status:
params["externalStatus"] = external_status
if tags:
params["tags"] = tags
if task_name:
params["taskName"] = task_name
if offset:
params["offset"] = offset
if limit:
params["limit"] = limit
return self.api.get_request(endpoint, params=params)

def get_sequential_image_tasks(
self,
Expand Down Expand Up @@ -1134,6 +1197,96 @@ def create_integrated_image_classification_task(
self.__fill_assign_users(payload, **kwargs)

return self.api.post_request(endpoint, payload=payload)

def create_multi_image_classification_task(
self,
project: str,
name: str,
folder_path: str,
status: str = None,
external_status: str = None,
priority: Priority = None,
attributes: list = [],
tags: list = [],
is_delete_exif: bool = False,
**kwargs,
) -> str:
"""
Create a single multi image classification task.

project is slug of your project (Required).
name is an unique identifier of task in your project (Required).
folder_path is a path to data folder. Files should be under the folder.
status can be 'registered', 'completed', 'skipped', 'reviewed', 'sent_back',
'approved', 'declined' (Optional).
external_status can be 'registered', 'completed', 'skipped', 'reviewed',
priority is the priority of the task (default: none) (Optional).
Set one of the numbers corresponding to:
none = 0,
low = 10,
medium = 20,
high = 30,
'sent_back', 'approved', 'declined', 'customer_declined' (Optional).
attributes is a list of attribute to be set in advance (Optional).
tags is a list of tag to be set in advance (Optional).
assignee is slug of assigned user (Optional).
reviewer is slug of review user (Optional).
approver is slug of approve user (Optional).
external_assignee is slug of external assigned user (Optional).
external_reviewer is slug of external review user (Optional).
external_approver is slug of external approve user (Optional).
"""
endpoint = "tasks/multi-image/classification"
if not os.path.isdir(folder_path):
raise FastLabelInvalidException("Folder does not exist.", 422)
file_paths = glob.glob(os.path.join(folder_path, "*"))
if not file_paths:
raise FastLabelInvalidException("Folder does not have any file.", 422)
contents = []
contents_size = 0
for file_path in file_paths:
if not utils.is_image_supported_ext(file_path):
raise FastLabelInvalidException(
"Supported extensions are png, jpg, jpeg.", 422
)

if not utils.is_image_supported_size(file_path):
raise FastLabelInvalidException(
"Supported image size is under 20 MB.", 422
)

if len(contents) == 6:
raise FastLabelInvalidException(
"The count of files should be under 6", 422
)

file = utils.base64_encode(file_path)
contents.append({"name": os.path.basename(file_path), "file": file})
contents_size += utils.get_json_length(contents[-1])
if contents_size > const.SUPPORTED_CONTENTS_SIZE:
raise FastLabelInvalidException(
"Supported contents size is under"
f" {const.SUPPORTED_CONTENTS_SIZE}.",
422,
)

payload = {"project": project, "name": name, "contents": contents}
if status:
payload["status"] = status
if external_status:
payload["externalStatus"] = external_status
if priority is not None:
payload["priority"] = priority
if attributes:
payload["attributes"] = delete_extra_attributes_parameter(attributes)
if tags:
payload["tags"] = tags
if is_delete_exif:
payload["isDeleteExif"] = is_delete_exif

self.__fill_assign_users(payload, **kwargs)

return self.api.post_request(endpoint, payload=payload)

def create_sequential_image_task(
self,
Expand Down Expand Up @@ -1982,6 +2135,56 @@ def update_image_classification_task(
self.__fill_assign_users(payload, **kwargs)

return self.api.put_request(endpoint, payload=payload)

def update_multi_image_classification_task(
self,
task_id: str,
status: str = None,
external_status: str = None,
priority: Priority = None,
attributes: list = [],
tags: list = [],
**kwargs,
) -> str:
"""
Update a single multi image classification task.

task_id is an id of the task (Required).
status can be 'registered', 'completed', 'skipped', 'reviewed', 'sent_back',
'approved', 'declined' (Optional).
external_status can be 'registered', 'completed', 'skipped', 'reviewed',
priority is the priority of the task (default: none) (Optional).
Set one of the numbers corresponding to:
none = 0,
low = 10,
medium = 20,
high = 30,
'sent_back', 'approved', 'declined', 'customer_declined' (Optional).
attributes is a list of attribute to be set in advance (Optional).
tags is a list of tag to be set in advance (Optional).
assignee is slug of assigned user (Optional).
reviewer is slug of review user (Optional).
approver is slug of approve user (Optional).
external_assignee is slug of external assigned user (Optional).
external_reviewer is slug of external review user (Optional).
external_approver is slug of external approve user (Optional).
"""
endpoint = "tasks/multi-image/classification/" + task_id
payload = {}
if status:
payload["status"] = status
if external_status:
payload["externalStatus"] = external_status
if priority is not None:
payload["priority"] = priority
if attributes:
payload["attributes"] = delete_extra_attributes_parameter(attributes)
if tags:
payload["tags"] = tags

self.__fill_assign_users(payload, **kwargs)

return self.api.put_request(endpoint, payload=payload)

def update_sequential_image_task(
self,
Expand Down