cvat-ai / cvat

Annotate better with CVAT, the industry-leading data engine for machine learning. Used and trusted by teams at any scale, for data of any scale.
https://cvat.ai
MIT License
12.58k stars 3k forks source link

Can't upload images with DataRequest method #5847

Closed quaid281 closed 1 year ago

quaid281 commented 1 year ago

I'm attempting to upload images to my task. Why would this code '''

Create a TasksApi instance

    tasks_api = TasksApi(api_client=api_client)

    # Get the task
    task = tasks_api.retrieve(task_id)
    # Upload the images
    for image_path in image_paths:
        image_name = os.path.basename(image_path)
        if image_name.endswith(".jpg") or image_name.endswith(".png"):
            with open(os.path.join(data_path, image_name), "rb") as f:
                file_bytes = f.read()
            data_request = DataRequest(name=image_name,image_quality=75,chunk_size=0,image_data=file_bytes)
            tasks_api.create_data(id=task_id, data_request=data_request)
            name = task[0]['name']
        print(f'Uploaded {image_name} to task {name} ({task_id})')

''' Give this error: File "C:\Users\AXW0J9E\Downloads\FPLAir\automaticProjectCreationv5.py", line 55, in create_cvat_task data_request = DataRequest(name=image_name,image_quality=75,chunk_size=0,image_data=file_bytes) File "C:\Users\AXW0J9E\AppData\Local\miniconda3\envs\qaqc\lib\site-packages\cvat_sdk\api_client\model_utils.py", line 1465, in attempt_convert_item raise get_type_error(input_value, path_to_item, valid_classes, cvat_sdk.api_client.exceptions.ApiTypeError: Invalid type for variable 'image_data'. Required value type is one of [NoneType, bool, date, datetime, dict, float, int, list, str] and passed type was bytes at ['image_data']

I'm lost on how I could fix this. I could not include in the file_bytes as a parameter in DataRequest and use this instead: ''' data_request = DataRequest(name=image_name,image_quality=75) tasks_api.create_data(id=task_id, data_request=data_request) ''' However, by using the code doesn't crash but no images are uploaded in CVAT.

zhiltsov-max commented 1 year ago

Hi. Please use this code snippet for file uploads with the lower-level SDK API. There are some extra efforts needed to pass files via this API. Please also consider using higher level API, which makes this process much more simple.

quaid281 commented 1 year ago

That's not easy for me to read and understand. Is there another way, or is there an example of how to use this snippet with a image_path from a local directory?

zhiltsov-max commented 1 year ago

Please check the documentation here.

If you need to pass other parameters than just files and image_quality, consider this sample:

```python from http import HTTPStatus from time import sleep from cvat_sdk import models from cvat_sdk.api_client import ApiClient, Configuration, apis def wait_until_task_is_created(api: apis.TasksApi, task_id: int) -> models.RqStatus: for _ in range(100): (status, _) = api.retrieve_status(task_id) if status.state.value in ["Finished", "Failed"]: return status sleep(1) raise Exception("Cannot create task") def create_task(api_client: ApiClient, spec: dict, data: dict, **kwargs) -> int: (task, response) = api_client.tasks_api.create(spec, **kwargs) assert response.status == HTTPStatus.CREATED if data.get("client_files"): # Can't encode binary files in json, use multipart/form-data instead (_, response) = api_client.tasks_api.create_data( task.id, data_request=models.DataRequest( client_files=data["client_files"], image_quality=data["image_quality"], ), upload_start=True, upload_multiple=True, _content_type="multipart/form-data", **kwargs, ) assert response.status == HTTPStatus.OK data = data.copy() del data["client_files"] # Pass the remaining parameters in this request and finish uploading (_, response) = api_client.tasks_api.create_data( task.id, data_request=models.DataRequest(**data), upload_finish=True, **kwargs ) assert response.status == HTTPStatus.ACCEPTED status = wait_until_task_is_created(api_client.tasks_api, task.id) assert status.state.value == "Finished" return task.id # check the docs about auth methods: # https://opencv.github.io/cvat/docs/api_sdk/sdk/lowlevel-api/#apiclient-and-configuration with ApiClient(Configuration(host="localhost", username="user", password="password")) as api_client: task_id = create_task(api_client, spec={ "name": "task with data", "labels": [{ "name": "cat" }] }, data={ "client_files": [ open('image1.jpg', 'rb') ], "image_quality": 70, "sorting_method": "lexicographical" } ) ```

Is there another way

Use the high-level SDK API:

from cvat_sdk import make_client
from cvat_sdk.core.proxies.tasks import ResourceType

with make_client("localhost", credentials=("user", "password")) as client:
    task = client.tasks.create_from_data(
        spec={
            "name": "task with local data",
            "labels": [ { "name": "car" } ],
        },
        data_params={
            "image_quality": 75,
        },
        resource_type=ResourceType.LOCAL,
        resources=["image.jpg"],
    )
quaid281 commented 1 year ago

@zhiltsov-max wow man ...that worked perfectly. Thank you so much for the example

alijawad07 commented 1 year ago

I am trying to upload the images by creating a task in an already existing project inside an organization, but this does not work. I am able to create the task without any media but when i try to attach media with it, im unable to do so.

zhiltsov-max commented 1 year ago

@alijawad07, do you receive any error? When working in an organization, please add client.organization_slug = "orgslug" before creating the task.