From 92492241833d06803d7a2282ace3e55bcbab686b Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Fri, 27 Jan 2023 00:13:17 +0100 Subject: [PATCH 1/5] Using Roboflow Universe datasets for training detection, segmentation and classification --- README.md | 8 +++++++ requirements.txt | 2 +- yolov5/classify/train.py | 12 ++++++++++ yolov5/segment/train.py | 13 +++++++++++ yolov5/train.py | 21 +++++++++++++----- yolov5/utils/roboflow.py | 47 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 yolov5/utils/roboflow.py diff --git a/README.md b/README.md index b7e8fa2..72219b6 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,14 @@ val_image_dir: "val_image_dir/" $ yolov5 train --data data.yaml --weights yolov5s.pt ``` +- Train your model using [Roboflow Universe](https://universe.roboflow.com/) datasets (roboflow>=0.2.27 required): + +```bash +$ yolov5 train --data DATASET_UNIVERSE_URL --weights yolov5s.pt --roboflow_token YOUR_ROBOFLOW_TOKEN +``` + +Where `DATASET_UNIVERSE_URL` must be in `https://universe.roboflow.com/workspace_name/project_name/project_version` format. + - Visualize your experiments via [Neptune.AI](https://neptune.ai/) (neptune-client>=0.10.10 required): ```bash diff --git a/requirements.txt b/requirements.txt index c7c8512..4af966e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -45,7 +45,7 @@ seaborn>=0.11.0 # mss # screenshots # albumentations>=1.0.3 # pycocotools>=2.0 # COCO mAP -# roboflow +# roboflow>=0.2.27 # ultralytics # HUB https://hub.ultralytics.com # CLI diff --git a/yolov5/classify/train.py b/yolov5/classify/train.py index 7d75cc8..9e17e3c 100644 --- a/yolov5/classify/train.py +++ b/yolov5/classify/train.py @@ -31,6 +31,7 @@ from tqdm import tqdm from yolov5.utils.downloads import attempt_donwload_from_hub +from yolov5.utils.roboflow import check_dataset_roboflow FILE = Path(__file__).resolve() ROOT = FILE.parents[1] # YOLOv5 root directory @@ -302,6 +303,9 @@ def parse_opt(known=False): parser.add_argument('--neptune_token', type=str, default=None, help='neptune.ai api token') parser.add_argument('--neptune_project', type=str, default=None, help='https://docs.neptune.ai/api-reference/neptune') + # Roboflow arguments + parser.add_argument('--roboflow_token', type=str, default=None, help='roboflow api token') + return parser.parse_known_args()[0] if known else parser.parse_args() @@ -312,6 +316,14 @@ def main(opt): check_git_status() check_requirements() + if "roboflow.com" in opt.data: + opt.data = check_dataset_roboflow( + data=opt.data, + roboflow_token=opt.roboflow_token, + task="classify", + location=ROOT.absolute().as_posix() + ) + # DDP mode device = select_device(opt.device, batch_size=opt.batch_size) if LOCAL_RANK != -1: diff --git a/yolov5/segment/train.py b/yolov5/segment/train.py index c6a9c53..9148402 100644 --- a/yolov5/segment/train.py +++ b/yolov5/segment/train.py @@ -33,6 +33,8 @@ from torch.optim import lr_scheduler from tqdm import tqdm +from yolov5.utils.roboflow import check_dataset_roboflow + FILE = Path(__file__).resolve() ROOT = FILE.parents[1] # YOLOv5 root directory if str(ROOT) not in sys.path: @@ -509,6 +511,9 @@ def parse_opt(known=False): parser.add_argument('--neptune_token', type=str, default=None, help='neptune.ai api token') parser.add_argument('--neptune_project', type=str, default=None, help='https://docs.neptune.ai/api-reference/neptune') + # Roboflow arguments + parser.add_argument('--roboflow_token', type=str, default=None, help='roboflow api token') + return parser.parse_known_args()[0] if known else parser.parse_args() @@ -519,6 +524,14 @@ def main(opt, callbacks=Callbacks()): check_git_status() check_requirements() + if "roboflow.com" in opt.data: + opt.data = check_dataset_roboflow( + data=opt.data, + roboflow_token=opt.roboflow_token, + task="segment", + location=ROOT.absolute().as_posix() + ) + # Resume if opt.resume and not opt.evolve: # resume from specified or most recent last.pt last = Path(check_file(opt.resume) if isinstance(opt.resume, str) else get_latest_run()) diff --git a/yolov5/train.py b/yolov5/train.py index 7235025..ef0539a 100644 --- a/yolov5/train.py +++ b/yolov5/train.py @@ -34,6 +34,7 @@ from torch.optim import lr_scheduler from tqdm import tqdm from yolov5.helpers import convert_coco_dataset_to_yolo, push_to_hfhub, upload_to_s3 +from yolov5.utils.roboflow import check_dataset_roboflow FILE = Path(__file__).resolve() ROOT = FILE.parents[0] # YOLOv5 root directory @@ -49,11 +50,10 @@ from yolov5.utils.callbacks import Callbacks from yolov5.utils.dataloaders import create_dataloader from yolov5.utils.downloads import attempt_donwload_from_hub, attempt_download, is_url -from yolov5.utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, check_dataset, check_file, check_git_info, - check_git_status, check_img_size, check_requirements, check_suffix, check_yaml, colorstr, - get_latest_run, increment_path, init_seeds, intersect_dicts, labels_to_class_weights, - labels_to_image_weights, methods, one_cycle, print_args, print_mutation, strip_optimizer, - yaml_save) +from yolov5.utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, check_dataset, check_file, check_img_size, + check_suffix, check_yaml, colorstr, get_latest_run, increment_path, init_seeds, + intersect_dicts, labels_to_class_weights, labels_to_image_weights, methods, one_cycle, + print_args, print_mutation, strip_optimizer, yaml_save) from yolov5.utils.loggers import Loggers from yolov5.utils.loggers.comet.comet_utils import check_comet_resume from yolov5.utils.loss import ComputeLoss @@ -538,6 +538,9 @@ def parse_opt(known=False): parser.add_argument('--hf_private', action='store_true', help='upload model to private repo') parser.add_argument('--hf_dataset_id', type=str, default=None, help='huggingface dataset id to link the model') + # Roboflow arguments + parser.add_argument('--roboflow_token', type=str, default=None, help='roboflow api token') + return parser.parse_known_args()[0] if known else parser.parse_args() @@ -548,6 +551,14 @@ def main(opt, callbacks=Callbacks()): #check_git_status() #check_requirements() + if "roboflow.com" in opt.data: + opt.data = check_dataset_roboflow( + data=opt.data, + roboflow_token=opt.roboflow_token, + task="detect", + location=ROOT.absolute().as_posix() + ) + # Resume (from specified or most recent last.pt) if opt.resume and not check_comet_resume(opt) and not opt.evolve: last = Path(check_file(opt.resume) if isinstance(opt.resume, str) else get_latest_run()) diff --git a/yolov5/utils/roboflow.py b/yolov5/utils/roboflow.py new file mode 100644 index 0000000..b243cd7 --- /dev/null +++ b/yolov5/utils/roboflow.py @@ -0,0 +1,47 @@ +import os +import re + +from yolov5.utils.general import check_requirements + + +def extract_roboflow_metadata(url: str) -> tuple: + match = re.search(r'https://(?:app|universe)\.roboflow\.com/([^/]+)/([^/]+)(?:/dataset)?/([^/]+)', url) + if match: + workspace_name = match.group(1) + project_name = match.group(2) + project_version = match.group(3) + return workspace_name, project_name, project_version + else: + raise ValueError(f"Invalid Roboflow dataset url ❌ " + f"Expected: https://universe.roboflow.com/workspace_name/project_name/project_version. " + f"Given: {url}") + + +def resolve_roboflow_model_format(task: str) -> str: + task_format_mapping = { + "detect": "yolov8", + "segment": "yolov5", + "classify": "folder" + } + return task_format_mapping.get(task) + + +def check_dataset_roboflow(data: str, roboflow_token: str, task: str, location: str) -> str: + if roboflow_token is None: + raise ValueError("roboflow_token not found ❌") + + check_requirements("roboflow>=0.2.27") + from roboflow import Roboflow + + workspace_name, project_name, project_version = extract_roboflow_metadata(url=data) + os.environ["DATASET_DIRECTORY"] = location + rf = Roboflow(api_key=roboflow_token) + project = rf.workspace(workspace_name).project(project_name) + model_format = resolve_roboflow_model_format(task=task) + dataset = project.version(int(project_version)).download( + model_format=model_format, + overwrite=False + ) + if task == "classify": + return dataset.location + return f"{dataset.location}/data.yaml" From 257ae26bfac540a562c018b502bb2328def8805b Mon Sep 17 00:00:00 2001 From: fcakyon Date: Fri, 27 Jan 2023 09:40:17 +0300 Subject: [PATCH 2/5] add roboflow ci tests, attempt to fix type error --- .github/workflows/ci.yml | 7 +++++++ yolov5/train.py | 28 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d2d864..bc3aa24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,8 @@ jobs: python -m unittest - name: Test scripts + env: + ROBOFLOWAPIKEY: ${{ secrets.ROBOFLOW_API_KEY }} run: | pip install -e . # donwload coco formatted testing data @@ -89,3 +91,8 @@ jobs: yolov5 segment train --img 128 --weights fcakyon/yolov5n-seg-v7.0 --epochs 1 --device cpu # yolov5 segment val --img 128 --weights yolov5n-seg.pt --device cpu yolov5 segment predict --img 128 --weights yolov5n-seg.pt --device cpu + # roboflow + yolov5 detect --data https://universe.roboflow.com/jacob-solawetz/aerial-maritime/dataset/10 --weights yolov5/weights/yolov5n.pt --device cpu --roboflow_token ${{ env.ROBOFLOWAPIKEY }} + yolov5 classify train --data https://universe.roboflow.com/bagas-etcfr/flowerdata1/dataset/1 --img 128 --model yolov5n-cls.pt --epochs 1 --device cpu --roboflow_token ${{ env.ROBOFLOWAPIKEY }} + yolov5 segment train --data https://universe.roboflow.com/scaffolding/scaffolding-distance/dataset/2 --img 128 --weights yolov5n-seg.pt --epochs 1 --device cpu --roboflow_token ${{ env.ROBOFLOWAPIKEY }} + diff --git a/yolov5/train.py b/yolov5/train.py index ef0539a..7e8154d 100644 --- a/yolov5/train.py +++ b/yolov5/train.py @@ -25,7 +25,6 @@ from datetime import datetime from pathlib import Path - import numpy as np import torch import torch.distributed as dist @@ -33,7 +32,9 @@ import yaml from torch.optim import lr_scheduler from tqdm import tqdm -from yolov5.helpers import convert_coco_dataset_to_yolo, push_to_hfhub, upload_to_s3 + +from yolov5.helpers import (convert_coco_dataset_to_yolo, push_to_hfhub, + upload_to_s3) from yolov5.utils.roboflow import check_dataset_roboflow FILE = Path(__file__).resolve() @@ -49,18 +50,25 @@ from yolov5.utils.autobatch import check_train_batch_size from yolov5.utils.callbacks import Callbacks from yolov5.utils.dataloaders import create_dataloader -from yolov5.utils.downloads import attempt_donwload_from_hub, attempt_download, is_url -from yolov5.utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, check_dataset, check_file, check_img_size, - check_suffix, check_yaml, colorstr, get_latest_run, increment_path, init_seeds, - intersect_dicts, labels_to_class_weights, labels_to_image_weights, methods, one_cycle, - print_args, print_mutation, strip_optimizer, yaml_save) +from yolov5.utils.downloads import (attempt_donwload_from_hub, + attempt_download, is_url) +from yolov5.utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, + check_dataset, check_file, check_img_size, + check_suffix, check_yaml, colorstr, + get_latest_run, increment_path, init_seeds, + intersect_dicts, labels_to_class_weights, + labels_to_image_weights, methods, one_cycle, + print_args, print_mutation, strip_optimizer, + yaml_save) from yolov5.utils.loggers import Loggers from yolov5.utils.loggers.comet.comet_utils import check_comet_resume from yolov5.utils.loss import ComputeLoss from yolov5.utils.metrics import fitness from yolov5.utils.plots import plot_evolve -from yolov5.utils.torch_utils import (EarlyStopping, ModelEMA, de_parallel, select_device, smart_DDP, smart_optimizer, - smart_resume, torch_distributed_zero_first) +from yolov5.utils.torch_utils import (EarlyStopping, ModelEMA, de_parallel, + select_device, smart_DDP, + smart_optimizer, smart_resume, + torch_distributed_zero_first) LOCAL_RANK = int(os.getenv('LOCAL_RANK', -1)) # https://pytorch.org/docs/stable/elastic/run.html RANK = int(os.getenv('RANK', -1)) @@ -551,7 +559,7 @@ def main(opt, callbacks=Callbacks()): #check_git_status() #check_requirements() - if "roboflow.com" in opt.data: + if "roboflow.com" in str(opt.data): opt.data = check_dataset_roboflow( data=opt.data, roboflow_token=opt.roboflow_token, From 2816da65283279331a75f72100d0b21bf83bb1cc Mon Sep 17 00:00:00 2001 From: fcakyon Date: Fri, 27 Jan 2023 09:49:05 +0300 Subject: [PATCH 3/5] remove deprecated unitests --- tests/test_yolov5.py | 238 ++----------------------------------------- 1 file changed, 8 insertions(+), 230 deletions(-) diff --git a/tests/test_yolov5.py b/tests/test_yolov5.py index 201a8ec..7c28351 100644 --- a/tests/test_yolov5.py +++ b/tests/test_yolov5.py @@ -4,120 +4,8 @@ DEVICE = "cpu" -class TestYolov5FromUltralytics(unittest.TestCase): +class TestYolov5FromUltralytics(unittest.TestCase): def test_load_model(self): - from yolov5 import YOLOv5 - - # init model - model_path = TestConstants.YOLOV5S_MODEL_PATH - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=False) - yolov5.load_model() - - # check if loaded - self.assertNotEqual(yolov5.model, None) - - def test_load_model_on_init(self): - from yolov5 import YOLOv5 - - # init model - model_path = TestConstants.YOLOV5S_MODEL_PATH - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # check if loaded - self.assertNotEqual(yolov5.model, None) - - def test_predict(self): - from PIL import Image - from yolov5 import YOLOv5 - - # init yolov5s model - model_path = TestConstants.YOLOV5S_MODEL_PATH - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # prepare image - image_path = TestConstants.ZIDANE_IMAGE_PATH - image = Image.open(image_path) - - # perform inference - results = yolov5.predict(image, size=640, augment=False) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 4) - - # prepare image - image = image_path - - # perform inference - results = yolov5.predict(image, size=640, augment=True) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 5) - - # init yolov5l model - model_path = TestConstants.YOLOV5L_MODEL_PATH - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # prepare image - image_path = TestConstants.BUS_IMAGE_PATH - image = Image.open(image_path) - # perform inference - results = yolov5.predict(image, size=1280, augment=False) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 6) - - # prepare image - image = image_path - - # perform inference - results = yolov5.predict(image, size=1280, augment=False) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 6) - - # init yolov5s model - model_path = TestConstants.YOLOV5S_MODEL_PATH - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # prepare images - image_path1 = TestConstants.ZIDANE_IMAGE_PATH - image_path2 = TestConstants.BUS_IMAGE_PATH - image1 = Image.open(image_path1) - image2 = Image.open(image_path2) - - # perform inference with multiple images and test augmentation - results = yolov5.predict([image1, image2], size=1280, augment=True) - - # compare - self.assertEqual(results.n, 2) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 4) - self.assertEqual(len(results.pred[1]), 5) - - # prepare image - image_path1 = TestConstants.ZIDANE_IMAGE_PATH - image_path2 = TestConstants.BUS_IMAGE_PATH - image1 = image_path1 - image2 = image_path2 - - # perform inference - results = yolov5.predict([image1, image2], size=1280, augment=True) - - # compare - self.assertEqual(results.n, 2) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 4) - self.assertEqual(len(results.pred[1]), 5) - - def test_hublike_load_model(self): import yolov5 # init model @@ -127,10 +15,11 @@ def test_hublike_load_model(self): # check if loaded self.assertNotEqual(model, None) - def test_hublike_predict(self): - import yolov5 + def test_predict(self): from PIL import Image + import yolov5 + # init yolov5s model model_path = TestConstants.YOLOV5S_MODEL_PATH model = yolov5.load(model_path, device=DEVICE) @@ -182,120 +71,8 @@ def test_hublike_predict(self): self.assertEqual(len(results.pred[1]), 5) -class TestYolov5FromHuggingface(unittest.TestCase): +class TestYolov5FromHuggingface(unittest.TestCase): def test_load_model(self): - from yolov5 import YOLOv5 - - # init model - model_path = TestConstants.YOLOV5S_HUB_ID - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=False) - yolov5.load_model() - - # check if loaded - self.assertNotEqual(yolov5.model, None) - - def test_load_model_on_init(self): - from yolov5 import YOLOv5 - - # init model - model_path = TestConstants.YOLOV5S_HUB_ID - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # check if loaded - self.assertNotEqual(yolov5.model, None) - - def test_predict(self): - from PIL import Image - from yolov5 import YOLOv5 - - # init yolov5s model - model_path = TestConstants.YOLOV5S_HUB_ID - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # prepare image - image_path = TestConstants.ZIDANE_IMAGE_PATH - image = Image.open(image_path) - - # perform inference - results = yolov5.predict(image, size=640, augment=False) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 4) - - # prepare image - image = image_path - - # perform inference - results = yolov5.predict(image, size=640, augment=True) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 5) - - # init yolov5l model - model_path = TestConstants.YOLOV5L_MODEL_PATH - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # prepare image - image_path = TestConstants.BUS_IMAGE_PATH - image = Image.open(image_path) - # perform inference - results = yolov5.predict(image, size=1280, augment=False) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 6) - - # prepare image - image = image_path - - # perform inference - results = yolov5.predict(image, size=1280, augment=False) - - # compare - self.assertEqual(results.n, 1) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 6) - - # init yolov5s model - model_path = TestConstants.YOLOV5S_HUB_ID - yolov5 = YOLOv5(model_path, DEVICE, load_on_init=True) - - # prepare images - image_path1 = TestConstants.ZIDANE_IMAGE_PATH - image_path2 = TestConstants.BUS_IMAGE_PATH - image1 = Image.open(image_path1) - image2 = Image.open(image_path2) - - # perform inference with multiple images and test augmentation - results = yolov5.predict([image1, image2], size=1280, augment=True) - - # compare - self.assertEqual(results.n, 2) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 4) - self.assertEqual(len(results.pred[1]), 5) - - # prepare image - image_path1 = TestConstants.ZIDANE_IMAGE_PATH - image_path2 = TestConstants.BUS_IMAGE_PATH - image1 = image_path1 - image2 = image_path2 - - # perform inference - results = yolov5.predict([image1, image2], size=1280, augment=True) - - # compare - self.assertEqual(results.n, 2) - self.assertEqual(len(results.names), 80) - self.assertEqual(len(results.pred[0]), 4) - self.assertEqual(len(results.pred[1]), 5) - - def test_hublike_load_model(self): import yolov5 # init model @@ -305,10 +82,11 @@ def test_hublike_load_model(self): # check if loaded self.assertNotEqual(model, None) - def test_hublike_predict(self): - import yolov5 + def test_predict(self): from PIL import Image + import yolov5 + # init yolov5s model model_path = TestConstants.YOLOV5S_HUB_ID model = yolov5.load(model_path, device=DEVICE) From 6ce89eae45ae4431455c3e4cae2d36dfcdbe943a Mon Sep 17 00:00:00 2001 From: fcakyon Date: Fri, 27 Jan 2023 09:58:18 +0300 Subject: [PATCH 4/5] fix type errors in segment and classify --- yolov5/classify/train.py | 16 +++++++++++----- yolov5/segment/train.py | 28 +++++++++++++++++++--------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/yolov5/classify/train.py b/yolov5/classify/train.py index 9e17e3c..bd2c6ad 100644 --- a/yolov5/classify/train.py +++ b/yolov5/classify/train.py @@ -43,12 +43,18 @@ from yolov5.models.experimental import attempt_load from yolov5.models.yolo import ClassificationModel, DetectionModel from yolov5.utils.dataloaders import create_classification_dataloader -from yolov5.utils.general import (DATASETS_DIR, LOGGER, TQDM_BAR_FORMAT, WorkingDirectory, check_git_info, check_git_status, - check_requirements, colorstr, download, increment_path, init_seeds, print_args, yaml_save) +from yolov5.utils.general import (DATASETS_DIR, LOGGER, TQDM_BAR_FORMAT, + WorkingDirectory, check_git_info, + check_git_status, check_requirements, + colorstr, download, increment_path, + init_seeds, print_args, yaml_save) from yolov5.utils.loggers import GenericLogger from yolov5.utils.plots import imshow_cls -from yolov5.utils.torch_utils import (ModelEMA, model_info, reshape_classifier_output, select_device, smart_DDP, - smart_optimizer, smartCrossEntropyLoss, torch_distributed_zero_first) +from yolov5.utils.torch_utils import (ModelEMA, model_info, + reshape_classifier_output, select_device, + smart_DDP, smart_optimizer, + smartCrossEntropyLoss, + torch_distributed_zero_first) LOCAL_RANK = int(os.getenv('LOCAL_RANK', -1)) # https://pytorch.org/docs/stable/elastic/run.html RANK = int(os.getenv('RANK', -1)) @@ -316,7 +322,7 @@ def main(opt): check_git_status() check_requirements() - if "roboflow.com" in opt.data: + if "roboflow.com" in str(opt.data): opt.data = check_dataset_roboflow( data=opt.data, roboflow_token=opt.roboflow_token, diff --git a/yolov5/segment/train.py b/yolov5/segment/train.py index 9148402..d0a0b08 100644 --- a/yolov5/segment/train.py +++ b/yolov5/segment/train.py @@ -47,19 +47,29 @@ from yolov5.utils.autoanchor import check_anchors from yolov5.utils.autobatch import check_train_batch_size from yolov5.utils.callbacks import Callbacks -from yolov5.utils.downloads import attempt_donwload_from_hub, attempt_download, is_url -from yolov5.utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, check_dataset, check_file, check_git_info, - check_git_status, check_img_size, check_requirements, check_suffix, check_yaml, colorstr, - get_latest_run, increment_path, init_seeds, intersect_dicts, labels_to_class_weights, - labels_to_image_weights, one_cycle, print_args, print_mutation, strip_optimizer, yaml_save) +from yolov5.utils.downloads import (attempt_donwload_from_hub, + attempt_download, is_url) +from yolov5.utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, + check_dataset, check_file, check_git_info, + check_git_status, check_img_size, + check_requirements, check_suffix, check_yaml, + colorstr, get_latest_run, increment_path, + init_seeds, intersect_dicts, + labels_to_class_weights, + labels_to_image_weights, one_cycle, + print_args, print_mutation, strip_optimizer, + yaml_save) from yolov5.utils.loggers import GenericLogger from yolov5.utils.plots import plot_evolve, plot_labels from yolov5.utils.segment.dataloaders import create_dataloader from yolov5.utils.segment.loss import ComputeLoss from yolov5.utils.segment.metrics import KEYS, fitness -from yolov5.utils.segment.plots import plot_images_and_masks, plot_results_with_masks -from yolov5.utils.torch_utils import (EarlyStopping, ModelEMA, de_parallel, select_device, smart_DDP, smart_optimizer, - smart_resume, torch_distributed_zero_first) +from yolov5.utils.segment.plots import (plot_images_and_masks, + plot_results_with_masks) +from yolov5.utils.torch_utils import (EarlyStopping, ModelEMA, de_parallel, + select_device, smart_DDP, + smart_optimizer, smart_resume, + torch_distributed_zero_first) LOCAL_RANK = int(os.getenv('LOCAL_RANK', -1)) # https://pytorch.org/docs/stable/elastic/run.html RANK = int(os.getenv('RANK', -1)) @@ -524,7 +534,7 @@ def main(opt, callbacks=Callbacks()): check_git_status() check_requirements() - if "roboflow.com" in opt.data: + if "roboflow.com" in str(opt.data): opt.data = check_dataset_roboflow( data=opt.data, roboflow_token=opt.roboflow_token, From bb76e476e62f0158fe4482fa0115c3e41e176cff Mon Sep 17 00:00:00 2001 From: fcakyon Date: Fri, 27 Jan 2023 10:19:30 +0300 Subject: [PATCH 5/5] fix a typo in ci --- .github/workflows/ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc3aa24..1a8d18c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,8 @@ jobs: - name: Test scripts env: - ROBOFLOWAPIKEY: ${{ secrets.ROBOFLOW_API_KEY }} + ROBOFLOW_TOKEN: ${{ secrets.ROBOFLOW_API_KEY }} + shell: bash # for Windows compatibility run: | pip install -e . # donwload coco formatted testing data @@ -92,7 +93,7 @@ jobs: # yolov5 segment val --img 128 --weights yolov5n-seg.pt --device cpu yolov5 segment predict --img 128 --weights yolov5n-seg.pt --device cpu # roboflow - yolov5 detect --data https://universe.roboflow.com/jacob-solawetz/aerial-maritime/dataset/10 --weights yolov5/weights/yolov5n.pt --device cpu --roboflow_token ${{ env.ROBOFLOWAPIKEY }} - yolov5 classify train --data https://universe.roboflow.com/bagas-etcfr/flowerdata1/dataset/1 --img 128 --model yolov5n-cls.pt --epochs 1 --device cpu --roboflow_token ${{ env.ROBOFLOWAPIKEY }} - yolov5 segment train --data https://universe.roboflow.com/scaffolding/scaffolding-distance/dataset/2 --img 128 --weights yolov5n-seg.pt --epochs 1 --device cpu --roboflow_token ${{ env.ROBOFLOWAPIKEY }} + yolov5 train --data https://universe.roboflow.com/jacob-solawetz/aerial-maritime/dataset/10 --weights yolov5/weights/yolov5n.pt --device cpu --roboflow_token ${{ env.ROBOFLOW_TOKEN }} + yolov5 classify train --data https://universe.roboflow.com/bagas-etcfr/flowerdata1/dataset/1 --img 128 --model yolov5n-cls.pt --epochs 1 --device cpu --roboflow_token ${{ env.ROBOFLOW_TOKEN }} + yolov5 segment train --data https://universe.roboflow.com/scaffolding/scaffolding-distance/dataset/2 --img 128 --weights yolov5n-seg.pt --epochs 1 --device cpu --roboflow_token ${{ env.ROBOFLOW_TOKEN }}