Examples: query, "exact match", wildcard*, wild?ard, wild*rd
Fuzzy search: cake~ (finds cakes, bake)
Term boost: "red velvet"^4, chocolate^2
Field grouping: tags:(+work -"fun-stuff")
Escaping: Escape characters +-&|!(){}[]^"~*?:\ with \, e.g. \+
Range search: properties.timestamp:[1587729413488 TO *] (inclusive), properties.title:{A TO Z}(excluding A and Z)
Combinations: chocolate AND vanilla, chocolate OR vanilla, (chocolate OR vanilla) NOT "vanilla pudding"
Field search: properties.title:"The Title" AND text
Unanswered
Hello, Have Been Trying For A Long Time To Make A Task That Collect A Dataset From Cvat And Trains A Yolo Modell In Clearml. But Cannot Figure It Out And Get The Understanding On How We Actually Do This Following Best Practices. My Sync Script:

Hello, Have been trying for a long time to make a task that collect a dataset from cvat and trains a yolo modell in clearml. But cannot figure it out and get the understanding on how we actually do this following best practices.

My sync script:

import argparse
import tempfile
import zipfile
import time
from pathlib import Path
from urllib.parse import urlparse

from clearml import Dataset, Task
from cvat_sdk.api_client import ApiClient, Configuration
from cvat_sdk.exceptions import ApiException

# sync_dataset_to_clearml-funksjonen er uendret...
def sync_dataset_to_clearml(project_name: str, dataset_name: str, local_path: Path) -> str:
    print(f"Sjekker datasett '{dataset_name}' i prosjekt '{project_name}'...")
    latest_remote_dataset = None
    try:
        latest_remote_dataset = Dataset.get(
            dataset_project=project_name, dataset_name=dataset_name, only_latest=True)
        remote_hash = latest_remote_dataset.file_hash
        local_hash = Dataset.hash_local_folder(local_path)
        if remote_hash == local_hash:
            print(":white_check_mark: Datasettet er allerede synkronisert. Ingen endringer funnet.")
            return latest_remote_dataset.id
        print(":arrows_counterclockwise: Endringer oppdaget. Oppretter en ny versjon...")
    except ValueError:
        print(f"Finner ikke et eksisterende datasett. Oppretter første versjon.")
    new_dataset = Dataset.create(
        dataset_project=project_name, dataset_name=dataset_name,
        parent_datasets=[latest_remote_dataset] if latest_remote_dataset else None)
    new_dataset.add_files(path=local_path)
    new_dataset.upload()
    new_dataset.finalize()
    print(f":white_check_mark: Ny versjon '{new_dataset.version}' opprettet med ID: {new_dataset.id}")
    return new_dataset.id

def main():
    task = Task.init(
        project_name="Dataset Management",
        task_name="Sync CVAT Dataset",
        task_type=Task.TaskTypes.data_processing)
    parser = argparse.ArgumentParser(description="Synkroniser et CVAT-datasett til ClearML.")
    parser.add_argument("--cvat-url", required=True, help="URL til CVAT-serveren.")
    parser.add_argument("--cvat-user", required=True, help="Brukernavn for CVAT.")
    parser.add_argument("--cvat-password", required=True, help="Passord for CVAT.")
    parser.add_argument("--cvat-project-id", type=int, required=True, help="ID-en til prosjektet i CVAT.")
    parser.add_argument("--clearml-project", default="My Datasets", help="ClearML-prosjekt for datasettet.")
    parser.add_argument("--clearml-dataset-name", required=True, help="Navn på datasettet i ClearML.")
    args = parser.parse_args()
    task.connect(args)

    print("Kobler til CVAT-server...")
    with tempfile.TemporaryDirectory() as temp_dir:
        temp_path = Path(temp_dir)
        dataset_zip_path = temp_path / "dataset.zip"
        config = Configuration(host=args.cvat_url, username=args.cvat_user, password=args.cvat_password)
        with ApiClient(config) as api_client:
            print(f"Steg 1: Starter eksport-jobb for prosjekt ID: {args.cvat_project_id}...")
            # --- ENDRINGEN ER HER ---
            (request, _) = api_client.projects_api.create_dataset_export(
                id=args.cvat_project_id,
                format="Ultralytics YOLO Detection 1.0",
                save_images=True  # Forteller CVAT at vi vil ha med bildene
            )
            # --- SLUTT PÅ ENDRING ---
            rq_id = request.rq_id
            print(f"Eksport-jobb startet med Request ID: {rq_id}")

            print("Steg 2: Venter på at serveren skal klargjøre ZIP-filen...")
            final_status_request = None
            while True:
                try:
                    (status_request, _) = api_client.requests_api.retrieve(id=rq_id)
                    status = status_request.status.value
                    if status == "finished":
                        print(":white_check_mark: Eksporten er ferdig!")
                        final_status_request = status_request
                        break
                    elif status == "failed":
                        raise Exception("Eksport-jobben på CVAT-serveren feilet.")
                    print(f"Status er '{status}'. Venter 10 sekunder...")
                    time.sleep(10)
                except ApiException as e:
                    print(f"Feil under status-sjekk: {e}. Prøver igjen...")
                    time.sleep(10)

            print("Steg 3: Henter nedlastings-URL fra den ferdige jobben...")
            download_url = final_status_request.result_url
            if not download_url:
                raise Exception("CVAT returnerte ikke en 'result_url'. Kan ikke laste ned datasettet.")
            print(f"Funnet nedlastings-URL: {download_url}")

            parsed_url = urlparse(download_url)
            resource_path = parsed_url.path
            if parsed_url.query:
                resource_path += "?" + parsed_url.query

            print(f"Steg 4: Laster ned ZIP-fil fra ressurs-sti: {resource_path}...")
            (_, response) = api_client.call_api(
                resource_path=resource_path, method='GET',
                auth_settings=['basicAuth', 'cookieAuth', 'tokenAuth'],
                _parse_response=False, _request_timeout=600)
            status_code = response.status
            if status_code != 200:
                raise Exception(f"Nedlasting fra result_url feilet med statuskode {status_code}")

            print(f"Laster ned ZIP-fil til {dataset_zip_path}...")
            with open(dataset_zip_path, 'wb') as f:
                f.write(response.data)

            if dataset_zip_path.exists() and dataset_zip_path.stat().st_size > 100:
                print(f":white_check_mark: ZIP-filen er lastet ned og har en størrelse på {dataset_zip_path.stat().st_size} bytes.")
            else:
                raise FileNotFoundError("Nedlasting av ZIP-filen ser ut til å ha feilet.")

        unzip_dir = temp_path / "unzipped_data"
        unzip_dir.mkdir()
        print(f"Pakker ut datasettet til {unzip_dir}...")
        with zipfile.ZipFile(dataset_zip_path, 'r') as zip_ref:
            zip_ref.extractall(unzip_dir)

        print("Innhold i den utpakkede mappen:")
        for item in sorted(list(unzip_dir.iterdir())):
            print(f"- {item.name}")

        sync_dataset_to_clearml(
            project_name=args.clearml_project,
            dataset_name=args.clearml_dataset_name,
            local_path=unzip_dir)

    print("Jobb fullført!")

if __name__ == "__main__":
    main()

And my train script:

import argparse
import os
import yaml
from pathlib import Path
from ultralytics import YOLO
from clearml import Task, Dataset

def rewrite_path_files(directory: Path):
    """
    Går gjennom train.txt, val.txt, og test.txt i en mappe,
    og fjerner et overflødig 'data/' prefiks fra hver linje.
    Dette fikser vanlige feil i stier fra CVAT-eksporter.
    """
    files_to_process = ["train.txt", "val.txt", "test.txt"]
    print("--- Starter korrigering av stier i .txt-filer ---")

    for filename in files_to_process:
        filepath = directory / filename
        if filepath.exists():
            print(f"Behandler fil: {filepath}...")
            lines = filepath.read_text().splitlines()

            # Sjekker om korrigering er nødvendig ved å se på første linje
            if lines and (lines.lower().startswith("data/images") or lines.lower().startswith("./data/images")):
                corrected_lines = []
                for line in lines:
                    # Fjerner 'data/' eller './data/' og sikrer riktig casing for 'images'
                    # Eksempel: 'data/images/Train/...' -> 'images/train/...'
                    parts = Path(line).parts
                    try:
                        images_index = [p.lower() for p in parts].index('images')
                        correct_path = Path(*parts[images_index:])
                        corrected_lines.append(str(correct_path))
                    except ValueError:
                        corrected_lines.append(line)

                filepath.write_text("\n".join(corrected_lines))
                print(f":white_check_mark: Filen er korrigert. Ny første linje: {corrected_lines if corrected_lines else 'Tom fil'}")
            else:
                print(f":+1: Ingen korrigering nødvendig for {filename}.")
        else:
            print(f":information_source: Fant ikke {filename}, hopper over.")

    print("--- Ferdig med korrigering av stier ---")


def main(args):
    # Steg 1: Initialiser ClearML-task
    task = Task.init(project_name=args.clearml_project, task_name=args.task_name, task_type=Task.TaskTypes.training)
    task.connect(args)

    # Steg 2: Hent datasett fra ClearML
    print(f"Henter ClearML-datasett: Prosjekt='{args.dataset_project}', Navn='{args.dataset_name}'")
    try:
        dataset = Dataset.get(dataset_project=args.dataset_project, dataset_name=args.dataset_name)
        dataset_path = Path(dataset.get_local_copy())
        print(f"Datasett (ID: {dataset.id}, Versjon: {dataset.version}) lastet ned til: {dataset_path}")
    except Exception as e:
        print(f"Kunne ikke hente datasettet. Feilmelding: {e}")
        task.close()
        exit(1)

    # Steg 2.5: Fiks stier
    rewrite_path_files(dataset_path)

    # Steg 3: Finn data.yaml-filen
    data_yaml_path = dataset_path / "data.yaml"
    if not data_yaml_path.exists():
        print(f"FEIL: Fant ikke 'data.yaml' i datasettets rotmappe: {dataset_path}")
        task.close()
        exit(1)

    print(f"Fant konfigurasjonsfil: {data_yaml_path}")

    # Bytt arbeidsmappe til rotmappen for datasettet
    print(f"Bytter arbeidsmappe til: {dataset_path}")
    os.chdir(dataset_path)

    # Steg 4: Last inn modell og start trening
    print(f"Laster inn modell: {args.model_variant}")
    model = YOLO(args.model_variant)

    print(f"Starter trening for {args.epochs} epoker...")
    model.train(data="data.yaml", epochs=args.epochs, imgsz=args.imgsz)

    print("\n--- Trening fullført! ---")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Tren en YOLOv8-modell med data fra ClearML.")
    parser.add_argument("--clearml-project", type=str, default="Frigate V2")
    parser.add_argument("--task-name", type=str, default="YOLOv8 Training - Fixed Paths")
    parser.add_argument("--dataset-project", type=str, default="Frigate V2")
    parser.add_argument("--dataset-name", type=str, default="CVAT Frigate Dataset YOLO 1.1")
    parser.add_argument("--model-variant", type=str, default="yolov8s.pt")
    parser.add_argument("--epochs", type=int, default=50)
    parser.add_argument("--imgsz", type=int, default=640)
    arguments = parser.parse_args()
    main(arguments)

Have no qlue if this is made correctly the way clearml is designed to work?

  
  
Posted 13 hours ago
Votes Newest

Answers

13 Views
0 Answers
13 hours ago
2 hours ago
Tags