├── .DS_Store ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── albumentations.ipynb ├── coco2voc.ipynb ├── coco2yolosegmentation.ipynb ├── coco2yolov5.ipynb ├── coco_extract_subset.ipynb ├── dataset_splitting.ipynb ├── label_new_dataset.ipynb ├── pylabel2azure_custom_vision.ipynb ├── pylabeler.ipynb ├── voc2coco.ipynb ├── yolo2coco.ipynb ├── yolo2pylabeler.ipynb ├── yolo2voc.ipynb ├── yolo_with_yaml_importer.ipynb └── yolov5_training.ipynb /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pylabel-project/samples/a152a56b3f7a9b8db4d5ce9de2163ce7360aab1c/.DS_Store -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: pylabel 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # My Files 2 | sample.ipynb 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | pip-wheel-metadata/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | db.sqlite3 65 | db.sqlite3-journal 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 PyLabel Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Notebooks and code samples to help you use the PyLabel Python package and the PyLabeler Jupyter-based labeling tool. 2 | 3 | ## Annotation Format Conversion 4 | Use PyLabel to translate bounding box annotations between different formats-for example, from coco to yolo. 5 | - [coco2voc.ipynb](https://github.com/pylabel-project/samples/blob/main/coco2voc.ipynb) Open In Colab 6 | - [coco2yolov5.ipynb](https://github.com/pylabel-project/samples/blob/main/coco2yolov5.ipynb) Open In Colab 7 | - [voc2coco.ipynb](https://github.com/pylabel-project/samples/blob/main/voc2coco.ipynb) Open In Colab 8 | - [yolo2coco.ipynb](https://github.com/pylabel-project/samples/blob/main/yolo2coco.ipynb) Open In Colab 9 | - [yolo2voc.ipynb](https://github.com/pylabel-project/samples/blob/main/yolo2voc.ipynb) Open In Colab 10 | - [yolo_with_yaml_importer.ipynb](https://github.com/pylabel-project/samples/blob/main/yolo_with_yaml_importer.ipynb) Open In Colab 11 | 12 | ## PyLabeler 13 | PyLabeler is a Jupyter-based labeling tool that you can use to annotate images and edit bounding box annotations within a Jupyter notebook. 14 | - [**label_new_dataset.ipynb**](https://github.com/pylabel-project/samples/blob/main/label_new_dataset.ipynb) Open In Colab
This notebook is a labeling tool that can be used to annotate image datasets with bounding boxes, automatically suggest bounding boxes using an object detection model, and save the annotations in YOCO, COCO, or VOC format. 15 | - [**yolo2pylabeler.ipynb**](https://github.com/pylabel-project/samples/blob/main/yolo2pylabeler.ipynb) Open In Colab
This notebook uses PyLabeler to edit an existing dataset of Yolo annotations and save the new annotations back to Yolo format. 16 | 17 | ## Integrations with Other Tools 18 | PyLabel can help you use other tools that take bounding box annotations as an input or output. PyLabel stores annotations as a Pandas dataframe, which you can access directly to support your particular use case. 19 | 20 | - [**albumentations.ipynb**](https://github.com/pylabel-project/samples/blob/main/albumentations.ipynb) Open In Colab
If you don't have enough images to train a model well, you can use image augmenation to create more samples for training and validation. 21 | [Albumentations](https://albumentations.ai/) is a popular open-source library for creating additional, augmented images as well as the annotations for those images. 22 | 23 | - [**azure_custom_vision.ipynb**](https://github.com/pylabel-project/samples/blob/main/pylabel2azure_custom_vision.ipynb) Open In Colab
Using PyLabel you can import existing labels in COCO, YOLOv5, or VOC format and then upload the dataset to Azure Custom Vision. 24 | -------------------------------------------------------------------------------- /coco2yolosegmentation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": { 7 | "id": "Cxi8K9mXwl5t" 8 | }, 9 | "source": [ 10 | "\"Open \n", 11 | "\n", 12 | "# Convert Coco Segmentation Annotations to YOLO \n", 13 | "Yolo now supports segmentation. Use this notebook to try converting segmented annotations from Coco to Yolo format. " 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 1, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "import logging\n", 23 | "logging.getLogger().setLevel(logging.CRITICAL)\n", 24 | "!pip install pylabel > /dev/null" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 2, 30 | "metadata": { 31 | "id": "AYwWkeF4z1Sc" 32 | }, 33 | "outputs": [], 34 | "source": [ 35 | "from pylabel import importer" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "## Import coco annotations \n", 43 | "First we will import annotations from the coco dataset, which are in coco json format. " 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 3, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "--2023-01-15 17:32:37-- https://github.com/pylabel-project/pylabel/files/10416366/dataset.zip?raw=true\n", 56 | "Resolving github.com (github.com)... 192.30.255.112\n", 57 | "Connecting to github.com (github.com)|192.30.255.112|:443... connected.\n", 58 | "HTTP request sent, awaiting response... 302 Found\n", 59 | "Location: https://objects.githubusercontent.com/github-production-repository-file-5c1aeb/419178479/10416366?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20230116%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230116T013237Z&X-Amz-Expires=300&X-Amz-Signature=4f0bface806d84718180781a43838c441714eb0d0fc360b69de6c70b0e1eaf12&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=419178479&response-content-disposition=attachment%3Bfilename%3Ddataset.zip&response-content-type=application%2Fzip [following]\n", 60 | "--2023-01-15 17:32:37-- https://objects.githubusercontent.com/github-production-repository-file-5c1aeb/419178479/10416366?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20230116%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230116T013237Z&X-Amz-Expires=300&X-Amz-Signature=4f0bface806d84718180781a43838c441714eb0d0fc360b69de6c70b0e1eaf12&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=419178479&response-content-disposition=attachment%3Bfilename%3Ddataset.zip&response-content-type=application%2Fzip\n", 61 | "Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.109.133, ...\n", 62 | "Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.111.133|:443... connected.\n", 63 | "HTTP request sent, awaiting response... 200 OK\n", 64 | "Length: 15091452 (14M) [application/zip]\n", 65 | "Saving to: ‘data/dataset.zip’\n", 66 | "\n", 67 | "data/dataset.zip 100%[===================>] 14.39M 16.0MB/s in 0.9s \n", 68 | "\n", 69 | "2023-01-15 17:32:39 (16.0 MB/s) - ‘data/dataset.zip’ saved [15091452/15091452]\n", 70 | "\n" 71 | ] 72 | } 73 | ], 74 | "source": [ 75 | "import os \n", 76 | "import zipfile\n", 77 | "\n", 78 | "#Download sample dataset \n", 79 | "os.makedirs(\"data\", exist_ok=True)\n", 80 | "!wget \"https://github.com/pylabel-project/pylabel/files/10416366/dataset.zip?raw=true\" -O data/dataset.zip\n", 81 | "with zipfile.ZipFile(\"data/dataset.zip\", 'r') as zip_ref:\n", 82 | " zip_ref.extractall(\"data\")" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 4, 88 | "metadata": {}, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "text/html": [ 93 | "
\n", 94 | "\n", 107 | "\n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | "
img_folderimg_filenameimg_pathimg_idimg_widthimg_heightimg_depthann_segmentedann_bbox_xminann_bbox_ymin...ann_segmentationann_iscrowdann_poseann_truncatedann_difficultcat_idcat_namecat_supercategorysplitannotated
id
0IMG20221222121516.jpg130724096259.2846031465.132193...[[792.7838258164849, 2337.045101088646, 673.34...01Hanger1
1IMG20221222121516.jpg130724096390.6687401373.561431...[[1174.9922239502328, 2305.194401244167, 1131....01Hanger1
2IMG20221222121516.jpg130724096896.2986001485.038880...[[1624.8833592534984, 2185.7542768273706, 1541...01Hanger1
3IMG20221222121543.jpg2307240961855.8009331409.393468...[[1871.7262830482105, 2090.202177293934, 1915....01Hanger1
4IMG20221222121543.jpg2307240962438.1710731388.690513...[[3019.977190254017, 1809.119751166407, 2935.0...01Hanger1
\n", 281 | "

5 rows × 25 columns

\n", 282 | "
" 283 | ], 284 | "text/plain": [ 285 | " img_folder img_filename img_path img_id img_width img_height \\\n", 286 | "id \n", 287 | "0 IMG20221222121516.jpg 1 3072 4096 \n", 288 | "1 IMG20221222121516.jpg 1 3072 4096 \n", 289 | "2 IMG20221222121516.jpg 1 3072 4096 \n", 290 | "3 IMG20221222121543.jpg 2 3072 4096 \n", 291 | "4 IMG20221222121543.jpg 2 3072 4096 \n", 292 | "\n", 293 | " img_depth ann_segmented ann_bbox_xmin ann_bbox_ymin ... \\\n", 294 | "id ... \n", 295 | "0 259.284603 1465.132193 ... \n", 296 | "1 390.668740 1373.561431 ... \n", 297 | "2 896.298600 1485.038880 ... \n", 298 | "3 1855.800933 1409.393468 ... \n", 299 | "4 2438.171073 1388.690513 ... \n", 300 | "\n", 301 | " ann_segmentation ann_iscrowd ann_pose \\\n", 302 | "id \n", 303 | "0 [[792.7838258164849, 2337.045101088646, 673.34... 0 \n", 304 | "1 [[1174.9922239502328, 2305.194401244167, 1131.... 0 \n", 305 | "2 [[1624.8833592534984, 2185.7542768273706, 1541... 0 \n", 306 | "3 [[1871.7262830482105, 2090.202177293934, 1915.... 0 \n", 307 | "4 [[3019.977190254017, 1809.119751166407, 2935.0... 0 \n", 308 | "\n", 309 | " ann_truncated ann_difficult cat_id cat_name cat_supercategory split \\\n", 310 | "id \n", 311 | "0 1 Hanger \n", 312 | "1 1 Hanger \n", 313 | "2 1 Hanger \n", 314 | "3 1 Hanger \n", 315 | "4 1 Hanger \n", 316 | "\n", 317 | " annotated \n", 318 | "id \n", 319 | "0 1 \n", 320 | "1 1 \n", 321 | "2 1 \n", 322 | "3 1 \n", 323 | "4 1 \n", 324 | "\n", 325 | "[5 rows x 25 columns]" 326 | ] 327 | }, 328 | "execution_count": 4, 329 | "metadata": {}, 330 | "output_type": "execute_result" 331 | } 332 | ], 333 | "source": [ 334 | "#Specify path to the coco.json file\n", 335 | "path_to_annotations = \"data/project-2023-01-14-07-55-43.json\"\n", 336 | "#Specify the path to the images (if they are in a different folder than the annotations)\n", 337 | "path_to_images = \"\"\n", 338 | "\n", 339 | "#Import the dataset into the pylable schema \n", 340 | "dataset = importer.ImportCoco(path_to_annotations, path_to_images=path_to_images, name=\"Segmentation\")\n", 341 | "dataset.df.head(5)" 342 | ] 343 | }, 344 | { 345 | "attachments": {}, 346 | "cell_type": "markdown", 347 | "metadata": {}, 348 | "source": [ 349 | "# Export to Yolo v5 with Segmenttation \n", 350 | "The PyLabel exporter will export all of the annotations in the dataframe to the desired target format.\n", 351 | "Yolo creates one text file for each image in the dataset. Set segmentation=True to export segmentation annotations. " 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 5, 357 | "metadata": {}, 358 | "outputs": [ 359 | { 360 | "data": { 361 | "text/plain": [ 362 | "'training/labels/IMG20221222121516.txt'" 363 | ] 364 | }, 365 | "execution_count": 5, 366 | "metadata": {}, 367 | "output_type": "execute_result" 368 | } 369 | ], 370 | "source": [ 371 | "dataset.path_to_annotations = \"data/yolo\"\n", 372 | "dataset.export.ExportToYoloV5(segmentation=True)[1]" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 6, 378 | "metadata": {}, 379 | "outputs": [ 380 | { 381 | "name": "stdout", 382 | "output_type": "stream", 383 | "text": [ 384 | "1 0.25807 0.57057 0.21919 0.53169 0.19068 0.49572 0.16476 0.44907 0.14402 0.40047 0.12458 0.37033 0.08699 0.3577 0.0844 0.45879 0.20882 0.58418 \n", 385 | "1 0.38248 0.56279 0.36823 0.53558 0.32028 0.50544 0.27492 0.47823 0.24252 0.44421 0.21271 0.40047 0.18549 0.35089 0.17124 0.33631 0.15568 0.33534 0.13235 0.34603 0.12717 0.35089 0.13106 0.3577 0.15698 0.38783 0.18938 0.45393 0.2166 0.49086 0.26325 0.51905 0.30213 0.54335 0.34879 0.58029 \n", 386 | "1 0.52893 0.53363 0.50172 0.54821 0.4408 0.51614 0.38119 0.486 0.32805 0.43351 0.29176 0.38297 0.3138 0.36353 0.33712 0.36256 0.37082 0.37325 0.39804 0.41505 0.42007 0.44518 0.44988 0.47142 0.48876 0.49961 \n" 387 | ] 388 | } 389 | ], 390 | "source": [ 391 | "#View a sample of the segmentation annotations\n", 392 | "!cat 'training/labels/IMG20221222121516.txt'" 393 | ] 394 | } 395 | ], 396 | "metadata": { 397 | "colab": { 398 | "collapsed_sections": [], 399 | "name": "import2.ipynb", 400 | "provenance": [] 401 | }, 402 | "kernelspec": { 403 | "display_name": "Python 3.8.5 ('my-new-project')", 404 | "language": "python", 405 | "name": "python3" 406 | }, 407 | "language_info": { 408 | "codemirror_mode": { 409 | "name": "ipython", 410 | "version": 3 411 | }, 412 | "file_extension": ".py", 413 | "mimetype": "text/x-python", 414 | "name": "python", 415 | "nbconvert_exporter": "python", 416 | "pygments_lexer": "ipython3", 417 | "version": "3.8.5" 418 | }, 419 | "vscode": { 420 | "interpreter": { 421 | "hash": "b9d2b2088005b129b6cb174ba487de37c3e3acf6fca20d7f1b3d5131adeb2740" 422 | } 423 | } 424 | }, 425 | "nbformat": 4, 426 | "nbformat_minor": 2 427 | } 428 | -------------------------------------------------------------------------------- /coco_extract_subset.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [] 7 | }, 8 | { 9 | "cell_type": "markdown", 10 | "metadata": { 11 | "id": "Cxi8K9mXwl5t" 12 | }, 13 | "source": [ 14 | "# Extract annotations from COCO Dataset annotation file\n", 15 | "This notebook was created to answer a question from stackoverflow: [https://stackoverflow.com/questions/69722538/extract-annotations-from-coco-dataset-annotation-file](https://stackoverflow.com/questions/69722538/extract-annotations-from-coco-dataset-annotation-file)\n", 16 | "\n", 17 | "> I want to train on a subset of COCO dataset. For the images, I have created a folder of first 30k images of train2017 folder. Now I need annotations of those 30k images (extracted from instances_train2017.json) in a separate json file so that I can train it. How can I do it?\n", 18 | "\n", 19 | "The reason for the question is that Coco stores all of the annotations in one long json file, so there is no simple way to extract only the ones that you need. PyLabel can help with this task by importing the dataset, filtering the annotations to the images you care about, and then exporting back to a coco json file. \n" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 5, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "import logging\n", 34 | "logging.getLogger().setLevel(logging.CRITICAL)\n", 35 | "!pip install pylabel > /dev/null" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 6, 41 | "metadata": { 42 | "id": "AYwWkeF4z1Sc" 43 | }, 44 | "outputs": [], 45 | "source": [ 46 | "from pylabel import importer" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "# Download sample dataset \n", 54 | "For this example we can use a sample dataset stored in coco format. The general approach can later be applied to the full coco dataset." 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 7, 60 | "metadata": {}, 61 | "outputs": [ 62 | { 63 | "name": "stdout", 64 | "output_type": "stream", 65 | "text": [ 66 | "--2021-11-01 07:52:48-- https://github.com/pylabelalpha/notebook/blob/main/BCCD_coco.zip?raw=true\n", 67 | "Resolving github.com (github.com)... 192.30.255.112\n", 68 | "Connecting to github.com (github.com)|192.30.255.112|:443... connected.\n", 69 | "HTTP request sent, awaiting response... 302 Found\n", 70 | "Location: https://github.com/pylabelalpha/notebook/raw/main/BCCD_coco.zip [following]\n", 71 | "--2021-11-01 07:52:48-- https://github.com/pylabelalpha/notebook/raw/main/BCCD_coco.zip\n", 72 | "Reusing existing connection to github.com:443.\n", 73 | "HTTP request sent, awaiting response... 302 Found\n", 74 | "Location: https://raw.githubusercontent.com/pylabelalpha/notebook/main/BCCD_coco.zip [following]\n", 75 | "--2021-11-01 07:52:48-- https://raw.githubusercontent.com/pylabelalpha/notebook/main/BCCD_coco.zip\n", 76 | "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", 77 | "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", 78 | "HTTP request sent, awaiting response... 200 OK\n", 79 | "Length: 7625693 (7.3M) [application/zip]\n", 80 | "Saving to: ‘data/BCCD_coco.zip’\n", 81 | "\n", 82 | "data/BCCD_coco.zip 100%[===================>] 7.27M 21.2MB/s in 0.3s \n", 83 | "\n", 84 | "2021-11-01 07:52:50 (21.2 MB/s) - ‘data/BCCD_coco.zip’ saved [7625693/7625693]\n", 85 | "\n" 86 | ] 87 | }, 88 | { 89 | "data": { 90 | "text/html": [ 91 | "
\n", 92 | "\n", 105 | "\n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | "
img_folderimg_filenameimg_pathimg_idimg_widthimg_heightimg_depthann_segmentedann_bbox_xminann_bbox_ymin...ann_areaann_segmentationann_iscrowdann_poseann_truncatedann_difficultcat_idcat_namecat_supercategorysplit
id
0BloodImage_00315.jpgNone064048030164.0261.0...13699.0NoneNoneUnspecified000RBCNone
1BloodImage_00315.jpgNone06404803015.066.0...13699.0NoneNoneUnspecified000RBCNone
2BloodImage_00315.jpgNone06404803013.0234.0...11781.0NoneNoneUnspecified000RBCNone
3BloodImage_00315.jpgNone064048030239.03.0...11960.0NoneNoneUnspecified000RBCNone
4BloodImage_00315.jpgNone064048030542.0109.0...10290.0NoneNoneUnspecified100RBCNone
\n", 279 | "

5 rows × 24 columns

\n", 280 | "
" 281 | ], 282 | "text/plain": [ 283 | " img_folder img_filename img_path img_id img_width img_height \\\n", 284 | "id \n", 285 | "0 BloodImage_00315.jpg None 0 640 480 \n", 286 | "1 BloodImage_00315.jpg None 0 640 480 \n", 287 | "2 BloodImage_00315.jpg None 0 640 480 \n", 288 | "3 BloodImage_00315.jpg None 0 640 480 \n", 289 | "4 BloodImage_00315.jpg None 0 640 480 \n", 290 | "\n", 291 | " img_depth ann_segmented ann_bbox_xmin ann_bbox_ymin ... ann_area \\\n", 292 | "id ... \n", 293 | "0 3 0 164.0 261.0 ... 13699.0 \n", 294 | "1 3 0 15.0 66.0 ... 13699.0 \n", 295 | "2 3 0 13.0 234.0 ... 11781.0 \n", 296 | "3 3 0 239.0 3.0 ... 11960.0 \n", 297 | "4 3 0 542.0 109.0 ... 10290.0 \n", 298 | "\n", 299 | " ann_segmentation ann_iscrowd ann_pose ann_truncated ann_difficult \\\n", 300 | "id \n", 301 | "0 None None Unspecified 0 0 \n", 302 | "1 None None Unspecified 0 0 \n", 303 | "2 None None Unspecified 0 0 \n", 304 | "3 None None Unspecified 0 0 \n", 305 | "4 None None Unspecified 1 0 \n", 306 | "\n", 307 | " cat_id cat_name cat_supercategory split \n", 308 | "id \n", 309 | "0 0 RBC None \n", 310 | "1 0 RBC None \n", 311 | "2 0 RBC None \n", 312 | "3 0 RBC None \n", 313 | "4 0 RBC None \n", 314 | "\n", 315 | "[5 rows x 24 columns]" 316 | ] 317 | }, 318 | "execution_count": 7, 319 | "metadata": {}, 320 | "output_type": "execute_result" 321 | } 322 | ], 323 | "source": [ 324 | "import os \n", 325 | "import zipfile\n", 326 | "\n", 327 | "#Download and import sample coco dataset \n", 328 | "os.makedirs(\"data\", exist_ok=True)\n", 329 | "!wget \"https://github.com/pylabelalpha/notebook/blob/main/BCCD_coco.zip?raw=true\" -O data/BCCD_coco.zip\n", 330 | "with zipfile.ZipFile(\"data/BCCD_coco.zip\", 'r') as zip_ref:\n", 331 | " zip_ref.extractall(\"data\")\n", 332 | "\n", 333 | "#Specify path to the coco.json file\n", 334 | "path_to_annotations = \"data/BCCD_Dataset.json\"\n", 335 | "#Specify the path to the images (if they are in a different folder than the annotations)\n", 336 | "path_to_images = \"\"\n", 337 | "\n", 338 | "#Import the dataset into the pylable schema \n", 339 | "dataset = importer.ImportCoco(path_to_annotations, path_to_images=path_to_images, name=\"BCCD_coco\")\n", 340 | "dataset.df.head(5)" 341 | ] 342 | }, 343 | { 344 | "cell_type": "markdown", 345 | "metadata": {}, 346 | "source": [ 347 | "PyLabel imports the annotations into a pandas dataframe. Now you can filter this dataframe to the rows related to the images that you care about. There are 364 images in this dataset." 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 8, 353 | "metadata": { 354 | "colab": { 355 | "base_uri": "https://localhost:8080/" 356 | }, 357 | "id": "5R1rOJVL420b", 358 | "outputId": "ae94525b-c6d5-4a4f-d56d-7f1bd29a7411" 359 | }, 360 | "outputs": [ 361 | { 362 | "name": "stdout", 363 | "output_type": "stream", 364 | "text": [ 365 | "Number of images: 364\n", 366 | "Class counts:\n", 367 | "RBC 4155\n", 368 | "WBC 372\n", 369 | "Platelets 361\n", 370 | "Name: cat_name, dtype: int64\n" 371 | ] 372 | } 373 | ], 374 | "source": [ 375 | "print(f\"Number of images: {dataset.analyze.num_images}\")\n", 376 | "print(f\"Class counts:\\n{dataset.analyze.class_counts}\")" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "metadata": {}, 382 | "source": [ 383 | "## Extract images\n", 384 | "Lets copy some images to another directory to to represent the images that we care about. " 385 | ] 386 | }, 387 | { 388 | "cell_type": "code", 389 | "execution_count": 9, 390 | "metadata": {}, 391 | "outputs": [ 392 | { 393 | "name": "stdout", 394 | "output_type": "stream", 395 | "text": [ 396 | "mkdir: data/100Images/: File exists\n" 397 | ] 398 | } 399 | ], 400 | "source": [ 401 | "#Copy 100 images from the BCCD_Dataset/BCCD/JPEGImages/ to BCCD_Dataset/BCCD/100Images/ \n", 402 | "!mkdir data/100Images/ \n", 403 | "!ls data/*.jpg | head -100 | xargs -I{} cp {} data/100Images/ " 404 | ] 405 | }, 406 | { 407 | "cell_type": "markdown", 408 | "metadata": {}, 409 | "source": [ 410 | "Create a list with all of the files in this directory. " 411 | ] 412 | }, 413 | { 414 | "cell_type": "code", 415 | "execution_count": 10, 416 | "metadata": {}, 417 | "outputs": [ 418 | { 419 | "name": "stdout", 420 | "output_type": "stream", 421 | "text": [ 422 | "100 files including BloodImage_00000.jpg\n" 423 | ] 424 | } 425 | ], 426 | "source": [ 427 | "#Store a list of all of the files in the directory \n", 428 | "files = sorted(os.listdir('data/100Images/'))\n", 429 | "print(f\"{len(files)} files including {files[0]}\")" 430 | ] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "metadata": {}, 435 | "source": [ 436 | "Now filter the dataframe to only images in the list of files." 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": 11, 442 | "metadata": {}, 443 | "outputs": [ 444 | { 445 | "name": "stdout", 446 | "output_type": "stream", 447 | "text": [ 448 | "Number of images 100\n" 449 | ] 450 | } 451 | ], 452 | "source": [ 453 | "dataset.df = dataset.df[dataset.df.img_filename.isin(files)].reset_index()\n", 454 | "print(f\"Number of images {dataset.df.img_filename.nunique()}\")\n" 455 | ] 456 | }, 457 | { 458 | "cell_type": "markdown", 459 | "metadata": {}, 460 | "source": [ 461 | "# Export annotations back as a coso json file" 462 | ] 463 | }, 464 | { 465 | "cell_type": "code", 466 | "execution_count": 12, 467 | "metadata": {}, 468 | "outputs": [ 469 | { 470 | "data": { 471 | "text/plain": [ 472 | "['data/100Images/100Images_coco.json']" 473 | ] 474 | }, 475 | "execution_count": 12, 476 | "metadata": {}, 477 | "output_type": "execute_result" 478 | } 479 | ], 480 | "source": [ 481 | "dataset.path_to_annotations = 'data/100Images/'\n", 482 | "dataset.name = '100Images_coco'\n", 483 | "\n", 484 | "dataset.export.ExportToCoco()" 485 | ] 486 | } 487 | ], 488 | "metadata": { 489 | "colab": { 490 | "collapsed_sections": [], 491 | "name": "import2.ipynb", 492 | "provenance": [] 493 | }, 494 | "interpreter": { 495 | "hash": "de5e368ab5494158da905fb8b1c2e4fef8844fbfaace7cceca0beab983df3a80" 496 | }, 497 | "kernelspec": { 498 | "display_name": "Python 3.8.5 64-bit ('penv': venv)", 499 | "name": "python3" 500 | }, 501 | "language_info": { 502 | "codemirror_mode": { 503 | "name": "ipython", 504 | "version": 3 505 | }, 506 | "file_extension": ".py", 507 | "mimetype": "text/x-python", 508 | "name": "python", 509 | "nbconvert_exporter": "python", 510 | "pygments_lexer": "ipython3", 511 | "version": "3.8.5" 512 | } 513 | }, 514 | "nbformat": 4, 515 | "nbformat_minor": 2 516 | } 517 | -------------------------------------------------------------------------------- /label_new_dataset.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\"Open \n", 8 | "\n", 9 | " Documentation Status\n", 10 | "" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "id": "Cxi8K9mXwl5t" 17 | }, 18 | "source": [ 19 | "# Autolabel images with PyLabel, YOLOv5, and jupyter-bbox-widget\n", 20 | "This notebook is labeling tool that can used to annotate image datasets with bounding boxes, automatically suggest bounding boxes using an object detection model, and save the annotations in YOCO, COCO, or VOC format. \n", 21 | "\n", 22 | "The annotation interface uses the [jupyter-bbox-widget](https://github.com/gereleth/jupyter-bbox-widget). The bounding box detection uses PyTorch and a [VOLOv5](https://github.com/ultralytics/yolov5) model." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 1, 28 | "metadata": {}, 29 | "outputs": [ 30 | { 31 | "name": "stdout", 32 | "output_type": "stream", 33 | "text": [ 34 | "Note: you may need to restart the kernel to use updated packages.\n" 35 | ] 36 | } 37 | ], 38 | "source": [ 39 | "import logging\n", 40 | "logging.getLogger().setLevel(logging.CRITICAL)\n", 41 | "%pip install pylabel > /dev/null" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 2, 47 | "metadata": { 48 | "id": "AYwWkeF4z1Sc" 49 | }, 50 | "outputs": [], 51 | "source": [ 52 | "from pylabel import importer" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "## Import Images to Create a New Dataset\n", 60 | "In this example there are no annotations created yet. The path should be the path to a directory with the images that you want to annotate. For this demonstration we will download a subset of the coco dataset. " 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 3, 66 | "metadata": {}, 67 | "outputs": [ 68 | { 69 | "name": "stdout", 70 | "output_type": "stream", 71 | "text": [ 72 | "--2022-01-10 20:59:01-- https://github.com/ultralytics/yolov5/releases/download/v1.0/coco128.zip\n", 73 | "Resolving github.com (github.com)... 192.30.255.112\n", 74 | "Connecting to github.com (github.com)|192.30.255.112|:443... connected.\n", 75 | "HTTP request sent, awaiting response... 302 Found\n", 76 | "Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/264818686/7a208a00-e19d-11eb-94cf-5222600cc665?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20220111%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220111T045901Z&X-Amz-Expires=300&X-Amz-Signature=be5a6a8e9e904069734e102690defe3169e6bd5fabf6f590baad342825534153&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=264818686&response-content-disposition=attachment%3B%20filename%3Dcoco128.zip&response-content-type=application%2Foctet-stream [following]\n", 77 | "--2022-01-10 20:59:01-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/264818686/7a208a00-e19d-11eb-94cf-5222600cc665?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20220111%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220111T045901Z&X-Amz-Expires=300&X-Amz-Signature=be5a6a8e9e904069734e102690defe3169e6bd5fabf6f590baad342825534153&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=264818686&response-content-disposition=attachment%3B%20filename%3Dcoco128.zip&response-content-type=application%2Foctet-stream\n", 78 | "Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", 79 | "Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.108.133|:443... connected.\n", 80 | "HTTP request sent, awaiting response... 200 OK\n", 81 | "Length: 6984509 (6.7M) [application/octet-stream]\n", 82 | "Saving to: ‘data/coco128.zip’\n", 83 | "\n", 84 | "data/coco128.zip 100%[===================>] 6.66M 11.1MB/s in 0.6s \n", 85 | "\n", 86 | "2022-01-10 20:59:02 (11.1 MB/s) - ‘data/coco128.zip’ saved [6984509/6984509]\n", 87 | "\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "import os, zipfile\n", 93 | "\n", 94 | "#Download sample yolo dataset \n", 95 | "os.makedirs(\"data\", exist_ok=True)\n", 96 | "!wget \"https://github.com/ultralytics/yolov5/releases/download/v1.0/coco128.zip\" -O data/coco128.zip\n", 97 | "with zipfile.ZipFile(\"data/coco128.zip\", 'r') as zip_ref:\n", 98 | " zip_ref.extractall(\"data\")" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 4, 104 | "metadata": {}, 105 | "outputs": [ 106 | { 107 | "data": { 108 | "text/html": [ 109 | "
\n", 110 | "\n", 123 | "\n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | "
img_folderimg_filenameimg_pathimg_idimg_widthimg_heightimg_depthann_segmentedann_bbox_xminann_bbox_ymin...ann_segmentationann_iscrowdann_poseann_truncatedann_difficultcat_idcat_namecat_supercategorysplitannotated
id
0000000000612.jpgNaN06404803NaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaN
1000000000404.jpgNaN14266403NaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaN
2000000000438.jpgNaN26404803NaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaN
\n", 249 | "

3 rows × 25 columns

\n", 250 | "
" 251 | ], 252 | "text/plain": [ 253 | " img_folder img_filename img_path img_id img_width img_height \\\n", 254 | "id \n", 255 | "0 000000000612.jpg NaN 0 640 480 \n", 256 | "1 000000000404.jpg NaN 1 426 640 \n", 257 | "2 000000000438.jpg NaN 2 640 480 \n", 258 | "\n", 259 | " img_depth ann_segmented ann_bbox_xmin ann_bbox_ymin ... ann_segmentation \\\n", 260 | "id ... \n", 261 | "0 3 NaN NaN NaN ... NaN \n", 262 | "1 3 NaN NaN NaN ... NaN \n", 263 | "2 3 NaN NaN NaN ... NaN \n", 264 | "\n", 265 | " ann_iscrowd ann_pose ann_truncated ann_difficult cat_id cat_name \\\n", 266 | "id \n", 267 | "0 NaN NaN NaN NaN NaN \n", 268 | "1 NaN NaN NaN NaN NaN \n", 269 | "2 NaN NaN NaN NaN NaN \n", 270 | "\n", 271 | " cat_supercategory split annotated \n", 272 | "id \n", 273 | "0 NaN NaN NaN \n", 274 | "1 NaN NaN NaN \n", 275 | "2 NaN NaN NaN \n", 276 | "\n", 277 | "[3 rows x 25 columns]" 278 | ] 279 | }, 280 | "execution_count": 4, 281 | "metadata": {}, 282 | "output_type": "execute_result" 283 | } 284 | ], 285 | "source": [ 286 | "path_to_images = \"data/coco128/images/train2017\"\n", 287 | "dataset = importer.ImportImagesOnly(path=path_to_images, name=\"coco128\")\n", 288 | "dataset.df.head(3)" 289 | ] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": {}, 294 | "source": [ 295 | "## Predict and Edit Annotations\n", 296 | "Use the jupyter_bbox_widget to inspect, edit, and save annotations without leaving the Jupyter notebook. Press predict to autolabel images using a pretrained model. For instructions and keyboard shortcuts for using this widget see https://github.com/gereleth/jupyter-bbox-widget#Usage." 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": 5, 302 | "metadata": {}, 303 | "outputs": [ 304 | { 305 | "data": { 306 | "application/vnd.jupyter.widget-view+json": { 307 | "model_id": "eef0a9d413534c74ada849ee51608e55", 308 | "version_major": 2, 309 | "version_minor": 0 310 | }, 311 | "text/plain": [ 312 | "VBox(children=(HBox(children=(Label(value='000000000612.jpg (not annotated)'),)), HBox(children=(Button(icon='…" 313 | ] 314 | }, 315 | "metadata": {}, 316 | "output_type": "display_data" 317 | } 318 | ], 319 | "source": [ 320 | "classes = ['person','boat', 'bear', \"car\"]\n", 321 | "dataset.labeler.StartPyLaber(new_classes=classes)" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": {}, 327 | "source": [ 328 | "# Instructions \n", 329 | "- The first image (000000000612.jpg) should show some bears. Select the bear cleass draw some some boxes around the bears and then save.\n", 330 | "- The next image should be a boat. (000000000404.jpg) Select the boat class, draw boxes around the boats, and save.\n", 331 | "- When you see an image with an object that is not in the current list of classes, add it as new class, draw boxes on the image using that class and save. \n", 332 | "At anytime, run the cell below to see how many classes you have labeled in the dataset. " 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": 6, 338 | "metadata": {}, 339 | "outputs": [ 340 | { 341 | "data": { 342 | "text/plain": [ 343 | " 128\n", 344 | "Name: cat_name, dtype: int64" 345 | ] 346 | }, 347 | "execution_count": 6, 348 | "metadata": {}, 349 | "output_type": "execute_result" 350 | } 351 | ], 352 | "source": [ 353 | "dataset.analyze.class_counts" 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "execution_count": 8, 359 | "metadata": {}, 360 | "outputs": [ 361 | { 362 | "data": { 363 | "text/plain": [ 364 | "['training/dataset.yaml',\n", 365 | " 'training/labels/000000000612.txt',\n", 366 | " 'training/labels/000000000404.txt']" 367 | ] 368 | }, 369 | "execution_count": 8, 370 | "metadata": {}, 371 | "output_type": "execute_result" 372 | } 373 | ], 374 | "source": [ 375 | "#Export the annotations in Yolo format\n", 376 | "dataset.path_to_annotations = 'data/coco128/labels/newlabels/'\n", 377 | "os.makedirs(dataset.path_to_annotations, exist_ok=True)\n", 378 | "dataset.export.ExportToYoloV5()" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": null, 384 | "metadata": {}, 385 | "outputs": [], 386 | "source": [] 387 | } 388 | ], 389 | "metadata": { 390 | "colab": { 391 | "collapsed_sections": [], 392 | "name": "import2.ipynb", 393 | "provenance": [] 394 | }, 395 | "interpreter": { 396 | "hash": "de5e368ab5494158da905fb8b1c2e4fef8844fbfaace7cceca0beab983df3a80" 397 | }, 398 | "kernelspec": { 399 | "display_name": "Python 3.8.5 64-bit ('penv': venv)", 400 | "name": "python3" 401 | }, 402 | "language_info": { 403 | "codemirror_mode": { 404 | "name": "ipython", 405 | "version": 3 406 | }, 407 | "file_extension": ".py", 408 | "mimetype": "text/x-python", 409 | "name": "python", 410 | "nbconvert_exporter": "python", 411 | "pygments_lexer": "ipython3", 412 | "version": "3.8.5" 413 | } 414 | }, 415 | "nbformat": 4, 416 | "nbformat_minor": 2 417 | } 418 | -------------------------------------------------------------------------------- /pylabel2azure_custom_vision.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\"Open \n", 8 | "# Upload Annotations to Azure Custom Vision \n", 9 | "Custom Vision, part of the Azure Cognitive Services family, is a solution for training and deploying custom computer vision models. Custom Vision includes an API to upload images and annotations to train a custom model. Using PyLabel you can import existing labels in COCO, YOLOv5, or VOC format and then upload the dataset to Custom Vision. \n", 10 | "\n", 11 | "This notebook demonstrates how to import a custom dataset in YOLO format to Custom Vision. To complete the steps you will need an Azure Account and a Custom Vision subscription. Follow [this tutorial on the the Custom Vision site](https://docs.microsoft.com/en-us/azure/cognitive-services/custom-vision-service/quickstarts/object-detection?tabs=visual-studio&pivots=programming-language-python) to setup your account and make sure it is working before using this notebook to import a custom dataset. When you are ready to use this notebook to upload a custom dataset, it is recommended to open https://www.customvision.ai/ so you can see the results of the commands you are performing through the API. " 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 1, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "%pip install azure-cognitiveservices-vision-customvision\n", 21 | "%pip install pylabel\n", 22 | "\n", 23 | "#Import Azure cognitive services libraries \n", 24 | "from azure.cognitiveservices.vision.customvision.training import CustomVisionTrainingClient\n", 25 | "from azure.cognitiveservices.vision.customvision.prediction import CustomVisionPredictionClient\n", 26 | "from azure.cognitiveservices.vision.customvision.training.models import ImageFileCreateBatch, ImageFileCreateEntry, Region\n", 27 | "from msrest.authentication import ApiKeyCredentials\n", 28 | "\n", 29 | "#Import other libraries used in this notebook \n", 30 | "import os, zipfile\n", 31 | "from pathlib import PurePath\n", 32 | "from os.path import exists\n", 33 | "from decimal import *\n", 34 | "\n", 35 | "from pylabel import importer" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "# Replace with your Azure endpoint and subscription keys.\n", 45 | "ENDPOINT = \"\"\n", 46 | "training_key = \"\"\n", 47 | "prediction_key = \"\"\n", 48 | "prediction_resource_id = \"\"" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 3, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "#Initialize objects used by Azure Congitive vision\n", 58 | "credentials = ApiKeyCredentials(in_headers={\"Training-key\": training_key})\n", 59 | "trainer = CustomVisionTrainingClient(ENDPOINT, credentials)\n", 60 | "prediction_credentials = ApiKeyCredentials(in_headers={\"Prediction-key\": prediction_key})\n", 61 | "predictor = CustomVisionPredictionClient(ENDPOINT, prediction_credentials)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 4, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "#Create a new project\n", 71 | "publish_iteration_name = \"detectModel\"\n", 72 | "obj_detection_domain = next(domain for domain in trainer.get_domains() if domain.type == \"ObjectDetection\" and domain.name == \"General\")\n", 73 | "project = trainer.create_project(\"PyLabel Sample Dataset\", domain_id=obj_detection_domain.id)\n", 74 | "#If you browse to https://www.customvision.ai/ you should see a new project called \"PyLabel Sample Dataset\"" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "## Download Custom Dataset \n", 82 | "For this demonstration we will download 100 images from the squirrels and nuts dataset with annotations in YOLOv5 format. PyLabel can also import datasets in COCO and PASCAL VOC format. " 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 5, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "%%capture\n", 92 | "os.makedirs(\"data/\", exist_ok=True)\n", 93 | "!wget \"https://github.com/pylabel-project/datasets_models/blob/main/squirrelsandnuts/squirrelsandnuts_train.zip?raw=true\" -O data/squirrelsandnuts_train.zip\n", 94 | "with zipfile.ZipFile(\"data/squirrelsandnuts_train.zip\", 'r') as zip_ref:\n", 95 | " zip_ref.extractall(\"data/\")" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 6, 101 | "metadata": {}, 102 | "outputs": [ 103 | { 104 | "data": { 105 | "text/html": [ 106 | "
\n", 107 | "\n", 120 | "\n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | "
img_folderimg_filenameimg_pathimg_idimg_widthimg_heightimg_depthann_segmentedann_bbox_xminann_bbox_ymin...ann_segmentationann_iscrowdann_poseann_truncatedann_difficultcat_idcat_namecat_supercategorysplitannotated
id
0../../images/train2021-07-03T06-30-10-frame_0001.jpegNaN09605403NaN255.024170.991...NaNNaNNaNNaNNaN0SquirrelNaNNaN1
1../../images/train2021-07-03T06-47-39-frame_0004.jpegNaN19605403NaN650.016447.984...NaNNaNNaNNaNNaN1NutNaNNaN1
2../../images/train2021-07-03T06-47-39-frame_0004.jpegNaN19605403NaN690.480422.010...NaNNaNNaNNaNNaN1NutNaNNaN1
\n", 246 | "

3 rows × 25 columns

\n", 247 | "
" 248 | ], 249 | "text/plain": [ 250 | " img_folder img_filename img_path img_id \\\n", 251 | "id \n", 252 | "0 ../../images/train 2021-07-03T06-30-10-frame_0001.jpeg NaN 0 \n", 253 | "1 ../../images/train 2021-07-03T06-47-39-frame_0004.jpeg NaN 1 \n", 254 | "2 ../../images/train 2021-07-03T06-47-39-frame_0004.jpeg NaN 1 \n", 255 | "\n", 256 | " img_width img_height img_depth ann_segmented ann_bbox_xmin \\\n", 257 | "id \n", 258 | "0 960 540 3 NaN 255.024 \n", 259 | "1 960 540 3 NaN 650.016 \n", 260 | "2 960 540 3 NaN 690.480 \n", 261 | "\n", 262 | " ann_bbox_ymin ... ann_segmentation ann_iscrowd ann_pose \\\n", 263 | "id ... \n", 264 | "0 170.991 ... NaN NaN NaN \n", 265 | "1 447.984 ... NaN NaN NaN \n", 266 | "2 422.010 ... NaN NaN NaN \n", 267 | "\n", 268 | " ann_truncated ann_difficult cat_id cat_name cat_supercategory split \\\n", 269 | "id \n", 270 | "0 NaN NaN 0 Squirrel NaN NaN \n", 271 | "1 NaN NaN 1 Nut NaN NaN \n", 272 | "2 NaN NaN 1 Nut NaN NaN \n", 273 | "\n", 274 | " annotated \n", 275 | "id \n", 276 | "0 1 \n", 277 | "1 1 \n", 278 | "2 1 \n", 279 | "\n", 280 | "[3 rows x 25 columns]" 281 | ] 282 | }, 283 | "execution_count": 6, 284 | "metadata": {}, 285 | "output_type": "execute_result" 286 | } 287 | ], 288 | "source": [ 289 | "#Import annotations as a PyLabel dataset\n", 290 | "dataset = importer.ImportYoloV5(path=\"data/squirrelsandnuts_train/labels/train\",\n", 291 | " path_to_images=\"../../images/train\", \n", 292 | " img_ext=\"jpeg\",\n", 293 | " cat_names=['Squirrel','Nut']\n", 294 | " )\n", 295 | "dataset.df.head(3)" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": {}, 301 | "source": [ 302 | "## Import to Azure Custom Vision\n", 303 | "PyLabel stores the annotations as a pandas dataframe. Now you can use extract the annotations from the dataframe and use it as inputs to the Custom Vision APIs. \n", 304 | "\n", 305 | "The first step is to create tags for each of the classes in your custom dataset. A list of class names is available in the dataset.analyze.classes property. " 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": 7, 311 | "metadata": {}, 312 | "outputs": [ 313 | { 314 | "name": "stdout", 315 | "output_type": "stream", 316 | "text": [ 317 | "['Squirrel', 'Nut']\n" 318 | ] 319 | } 320 | ], 321 | "source": [ 322 | "print(dataset.analyze.classes)\n", 323 | "#Create a tag for each class and store then in a dict where the class name is the key\n", 324 | "tags = {}\n", 325 | "for class_name in dataset.analyze.classes:\n", 326 | " tag = trainer.create_tag(project.id, class_name)\n", 327 | " tags[class_name] = tag" 328 | ] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "metadata": {}, 333 | "source": [ 334 | "Now if you check your account on https://www.customvision.ai/ you should see a new project called \"PyLabel Sample Dataset\" with 2 tags added: Squirrels and Nuts. \n", 335 | "\n", 336 | "You are ready to upload your images and annotations. For each image in your dataset you will need to add \"Regions\" for each bounding box and then upload the image and annotations. " 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": 14, 342 | "metadata": {}, 343 | "outputs": [ 344 | { 345 | "name": "stdout", 346 | "output_type": "stream", 347 | "text": [ 348 | "Upload complete\n" 349 | ] 350 | } 351 | ], 352 | "source": [ 353 | "#Iterate the rows for each image in the dataframe\n", 354 | "for img_filename, img_df in dataset.df.groupby('img_filename'):\n", 355 | " img_path = str(PurePath(dataset.path_to_annotations, str(img_df.iloc[0].img_folder), img_filename))\n", 356 | " assert exists(img_path), f\"File does not exist: {img_path}\"\n", 357 | "\n", 358 | " #Create a region object for each bounding box in the dataset \n", 359 | " regions = []\n", 360 | " for index, row in img_df.iterrows():\n", 361 | "\n", 362 | " #Normalize the boundings box coordinates between 0 and 1\n", 363 | " x = Decimal(row.ann_bbox_xmin / row.img_width).min(1)\n", 364 | " y = Decimal(row.ann_bbox_ymin / row.img_height).min(1)\n", 365 | " w = Decimal(row.ann_bbox_width / row.img_width).min(1-x)\n", 366 | " h = Decimal(row.ann_bbox_height / row.img_height).min(1-y)\n", 367 | " \n", 368 | " regions.append(Region(\n", 369 | " tag_id=tags[row.cat_name].id, \n", 370 | " left=x,\n", 371 | " top=y,\n", 372 | " width=w,\n", 373 | " height=h\n", 374 | " )\n", 375 | " )\n", 376 | "\n", 377 | " #Create an object with the image and all of the annotations for that image\n", 378 | " with open(img_path, mode=\"rb\") as image_contents:\n", 379 | " image_and_annotations = [ImageFileCreateEntry(name=img_filename, contents=image_contents.read(), regions=regions)]\n", 380 | "\n", 381 | " #Upload the image and all annnotations for that image\n", 382 | " upload_result = trainer.create_images_from_files(\n", 383 | " project.id, \n", 384 | " ImageFileCreateBatch(images=image_and_annotations)\n", 385 | " )\n", 386 | " \n", 387 | " #If upload is not successful, print details about that image for debugging \n", 388 | " if not upload_result.is_batch_successful:\n", 389 | " print(\"Image upload failed.\")\n", 390 | " for image in upload_result.images:\n", 391 | " print(img_path)\n", 392 | " print(\"Image status: \", image.status)\n", 393 | " print(regions)\n", 394 | "\n", 395 | "#This will take a few minutes \n", 396 | "print(\"Upload complete\")\n" 397 | ] 398 | }, 399 | { 400 | "cell_type": "markdown", 401 | "metadata": {}, 402 | "source": [ 403 | "Now you should see all of your images uploaded to https://www.customvision.ai/.\n", 404 | "

\n", 405 | "\n", 406 | "

\n", 407 | "Click and image to see the bounding boxes.\n", 408 | "

\n", 409 | "\n", 410 | "

\n", 411 | "\n", 412 | "Now you are ready to train a model, which you can do at https://www.customvision.ai/. \n", 413 | "- If find a problem with this notebook, please report it as an issue here: https://github.com/pylabel-project/pylabel/issues \n", 414 | "- If have other questions, please start a discussion here: https://github.com/pylabel-project/pylabel/discussions. " 415 | ] 416 | } 417 | ], 418 | "metadata": { 419 | "interpreter": { 420 | "hash": "224f10583582cbeb83347e66d7d5874fb4e3ef8613e486088287d7c0b66e9aac" 421 | }, 422 | "kernelspec": { 423 | "display_name": "Python 3.8.5 64-bit ('venv': venv)", 424 | "language": "python", 425 | "name": "python3" 426 | }, 427 | "language_info": { 428 | "codemirror_mode": { 429 | "name": "ipython", 430 | "version": 3 431 | }, 432 | "file_extension": ".py", 433 | "mimetype": "text/x-python", 434 | "name": "python", 435 | "nbconvert_exporter": "python", 436 | "pygments_lexer": "ipython3", 437 | "version": "3.8.5" 438 | }, 439 | "orig_nbformat": 4 440 | }, 441 | "nbformat": 4, 442 | "nbformat_minor": 2 443 | } 444 | -------------------------------------------------------------------------------- /yolo_with_yaml_importer.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Pylabel_YoloWithYAML_Importer", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "zC-dG7dt6Ks-" 23 | }, 24 | "source": [ 25 | "This shows how PyLabel can import data when given a YAML File and a dataset that has already had its images and annotations/labels folders split into train, test and val. This is our expected use case." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "metadata": { 31 | "id": "ZlG6Nnec0EHi" 32 | }, 33 | "source": [ 34 | "import torch\n", 35 | "from IPython.display import Image # for displaying images\n", 36 | "import os, zipfile\n", 37 | "import random\n", 38 | "import shutil\n", 39 | "from sklearn.model_selection import train_test_split\n", 40 | "import xml.etree.ElementTree as ET\n", 41 | "from xml.dom import minidom\n", 42 | "from tqdm import tqdm\n", 43 | "from PIL import Image, ImageDraw\n", 44 | "import numpy as np\n", 45 | "import matplotlib.pyplot as plt\n", 46 | "\n", 47 | "random.seed(108)\n", 48 | "\n", 49 | "import logging\n", 50 | "logging.getLogger().setLevel(logging.CRITICAL)\n", 51 | "!pip install pylabel > /dev/null\n", 52 | "\n", 53 | "#!pip install pylabel\n", 54 | "\n", 55 | "from pylabel import importer\n", 56 | "from pylabel import *\n", 57 | "\n", 58 | "from pathlib import PurePath\n", 59 | "\n", 60 | "import yaml" 61 | ], 62 | "execution_count": 1, 63 | "outputs": [] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "metadata": { 68 | "colab": { 69 | "base_uri": "https://localhost:8080/" 70 | }, 71 | "id": "REHUX3HHhSeP", 72 | "outputId": "c286f4e2-9e83-48ab-8ef7-716ffc1cf01c" 73 | }, 74 | "source": [ 75 | "#A random dataset that we found online.\n", 76 | "!wget -O roadsign_splitdata.zip https://raw.githubusercontent.com/pylabel-project/datasets_models/main/roadsign_splitdata.zip\n", 77 | "!unzip roadsign_splitdata.zip\n" 78 | ], 79 | "execution_count": 2, 80 | "outputs": [ 81 | { 82 | "output_type": "stream", 83 | "name": "stdout", 84 | "text": [ 85 | "--2021-11-30 01:46:42-- https://raw.githubusercontent.com/pylabel-project/datasets_models/main/roadsign_splitdata.zip\n", 86 | "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", 87 | "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", 88 | "HTTP request sent, awaiting response... 200 OK\n", 89 | "Length: 22454439 (21M) [application/zip]\n", 90 | "Saving to: ‘roadsign_splitdata.zip’\n", 91 | "\n", 92 | "roadsign_splitdata. 100%[===================>] 21.41M 137MB/s in 0.2s \n", 93 | "\n", 94 | "2021-11-30 01:46:44 (137 MB/s) - ‘roadsign_splitdata.zip’ saved [22454439/22454439]\n", 95 | "\n", 96 | "Archive: roadsign_splitdata.zip\n", 97 | " inflating: annotations/test/road10.txt \n", 98 | " inflating: annotations/test/road29.txt \n", 99 | " inflating: annotations/test/road30.txt \n", 100 | " inflating: annotations/test/road38.txt \n", 101 | " inflating: annotations/test/road41.txt \n", 102 | " inflating: annotations/train/road0.txt \n", 103 | " inflating: annotations/train/road1.txt \n", 104 | " inflating: annotations/train/road12.txt \n", 105 | " inflating: annotations/train/road13.txt \n", 106 | " inflating: annotations/train/road14.txt \n", 107 | " inflating: annotations/train/road15.txt \n", 108 | " inflating: annotations/train/road16.txt \n", 109 | " inflating: annotations/train/road17.txt \n", 110 | " inflating: annotations/train/road18.txt \n", 111 | " inflating: annotations/train/road19.txt \n", 112 | " inflating: annotations/train/road2.txt \n", 113 | " inflating: annotations/train/road20.txt \n", 114 | " inflating: annotations/train/road21.txt \n", 115 | " inflating: annotations/train/road22.txt \n", 116 | " inflating: annotations/train/road23.txt \n", 117 | " inflating: annotations/train/road25.txt \n", 118 | " inflating: annotations/train/road26.txt \n", 119 | " inflating: annotations/train/road27.txt \n", 120 | " inflating: annotations/train/road28.txt \n", 121 | " inflating: annotations/train/road3.txt \n", 122 | " inflating: annotations/train/road31.txt \n", 123 | " inflating: annotations/train/road32.txt \n", 124 | " inflating: annotations/train/road33.txt \n", 125 | " inflating: annotations/train/road34.txt \n", 126 | " inflating: annotations/train/road35.txt \n", 127 | " inflating: annotations/train/road37.txt \n", 128 | " inflating: annotations/train/road39.txt \n", 129 | " inflating: annotations/train/road4.txt \n", 130 | " inflating: annotations/train/road40.txt \n", 131 | " inflating: annotations/train/road42.txt \n", 132 | " inflating: annotations/train/road5.txt \n", 133 | " inflating: annotations/train/road6.txt \n", 134 | " inflating: annotations/train/road8.txt \n", 135 | " inflating: annotations/train/road9.txt \n", 136 | " inflating: annotations/val/road11.txt \n", 137 | " inflating: annotations/val/road24.txt \n", 138 | " inflating: annotations/val/road36.txt \n", 139 | " inflating: annotations/val/road7.txt \n", 140 | " creating: images/test/\n", 141 | " inflating: images/test/road10.png \n", 142 | " inflating: images/test/road29.png \n", 143 | " inflating: images/test/road30.png \n", 144 | " inflating: images/test/road38.png \n", 145 | " inflating: images/test/road41.png \n", 146 | " creating: images/train/\n", 147 | " inflating: images/train/road0.png \n", 148 | " inflating: images/train/road1.png \n", 149 | " inflating: images/train/road12.png \n", 150 | " inflating: images/train/road13.png \n", 151 | " inflating: images/train/road14.png \n", 152 | " inflating: images/train/road15.png \n", 153 | " inflating: images/train/road16.png \n", 154 | " inflating: images/train/road17.png \n", 155 | " inflating: images/train/road18.png \n", 156 | " inflating: images/train/road19.png \n", 157 | " inflating: images/train/road2.png \n", 158 | " inflating: images/train/road20.png \n", 159 | " inflating: images/train/road21.png \n", 160 | " inflating: images/train/road22.png \n", 161 | " inflating: images/train/road23.png \n", 162 | " inflating: images/train/road25.png \n", 163 | " inflating: images/train/road26.png \n", 164 | " inflating: images/train/road27.png \n", 165 | " inflating: images/train/road28.png \n", 166 | " inflating: images/train/road3.png \n", 167 | " inflating: images/train/road31.png \n", 168 | " inflating: images/train/road32.png \n", 169 | " inflating: images/train/road33.png \n", 170 | " inflating: images/train/road34.png \n", 171 | " inflating: images/train/road35.png \n", 172 | " inflating: images/train/road37.png \n", 173 | " inflating: images/train/road39.png \n", 174 | " inflating: images/train/road4.png \n", 175 | " inflating: images/train/road40.png \n", 176 | " inflating: images/train/road42.png \n", 177 | " inflating: images/train/road5.png \n", 178 | " inflating: images/train/road6.png \n", 179 | " inflating: images/train/road8.png \n", 180 | " inflating: images/train/road9.png \n", 181 | " creating: images/val/\n", 182 | " inflating: images/val/road11.png \n", 183 | " inflating: images/val/road24.png \n", 184 | " inflating: images/val/road36.png \n", 185 | " inflating: images/val/road7.png \n", 186 | " inflating: road_sign_data.yaml \n" 187 | ] 188 | } 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "metadata": { 194 | "colab": { 195 | "base_uri": "https://localhost:8080/" 196 | }, 197 | "id": "nxYw2FbmhhQJ", 198 | "outputId": "64fad070-0e90-4a01-99ce-ea495994b60f" 199 | }, 200 | "source": [ 201 | "#An example annotation\n", 202 | "!cat /content/annotations/train/road4.txt" 203 | ], 204 | "execution_count": 3, 205 | "outputs": [ 206 | { 207 | "output_type": "stream", 208 | "name": "stdout", 209 | "text": [ 210 | "1 0.1891 0.4325 0.2285 0.3200\n", 211 | "1 0.5225 0.5425 0.1760 0.2750\n", 212 | "1 0.7903 0.6050 0.1648 0.2650\n" 213 | ] 214 | } 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "metadata": { 220 | "colab": { 221 | "base_uri": "https://localhost:8080/" 222 | }, 223 | "id": "L3lYwlImhhMN", 224 | "outputId": "d6513479-beb2-4fa7-9833-9dd89fe2fdee" 225 | }, 226 | "source": [ 227 | "#An example YAML file\n", 228 | "!cat /content/road_sign_data.yaml" 229 | ], 230 | "execution_count": 4, 231 | "outputs": [ 232 | { 233 | "output_type": "stream", 234 | "name": "stdout", 235 | "text": [ 236 | "train: images/train/ \n", 237 | "val: images/val/\n", 238 | "test: images/test/\n", 239 | "\n", 240 | "# number of classes\n", 241 | "nc: 4\n", 242 | "\n", 243 | "# class names\n", 244 | "names: [\"trafficlight\",\"stop\", \"speedlimit\",\"crosswalk\"]" 245 | ] 246 | } 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "metadata": { 252 | "id": "XFzuoZYjiR__" 253 | }, 254 | "source": [ 255 | "#Import the data from a YAML file and convert it to a dataset\n", 256 | "data0 = importer.ImportYoloV5WithYaml(yaml_file=\"/content/road_sign_data.yaml\", \n", 257 | " path_to_annotations=None, \n", 258 | " image_ext='png',\n", 259 | " name_of_annotations_folder=\"annotations\")" 260 | ], 261 | "execution_count": 7, 262 | "outputs": [] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "metadata": { 267 | "colab": { 268 | "base_uri": "https://localhost:8080/", 269 | "height": 258 270 | }, 271 | "id": "shMQ1ebViMHH", 272 | "outputId": "af4cfb26-40ab-42e4-8fae-df51dbccdb32" 273 | }, 274 | "source": [ 275 | "#An example of what the data looks like\n", 276 | "data0.df.head(5)" 277 | ], 278 | "execution_count": 10, 279 | "outputs": [ 280 | { 281 | "output_type": "execute_result", 282 | "data": { 283 | "text/html": [ 284 | "

\n", 285 | "\n", 298 | "\n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 405 | " \n", 406 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | "
img_folderimg_filenameimg_pathimg_idimg_widthimg_heightimg_depthann_segmentedann_bbox_xminann_bbox_yminann_bbox_xmaxann_bbox_ymaxann_bbox_widthann_bbox_heightann_areaann_segmentationann_iscrowdann_poseann_truncatedann_difficultcat_idcat_namecat_supercategorysplitannotated
id
0../../images/trainroad23.pngNaN02664003NaN216.00530125.9800241.99350178.980025.988253.00001377.3746NaNNaNNaNNaNNaN1stopNaNtrain1
1../../images/trainroad33.pngNaN12674003NaN23.002056.0200177.99555387.0200154.9935381.000059052.5235NaNNaNNaNNaNNaN1stopNaNtrain1
2../../images/trainroad8.pngNaN24003003NaN91.0000072.0150129.00000136.005038.000063.99002431.6200NaNNaNNaNNaNNaN1stopNaNtrain1
3../../images/trainroad8.pngNaN24003003NaN245.02000103.9950274.02000163.005029.000059.01001711.2900NaNNaNNaNNaNNaN1stopNaNtrain1
4../../images/trainroad16.pngNaN34002483NaN225.0000042.9908241.0000082.001216.000039.0104624.1664NaNNaNNaNNaNNaN1stopNaNtrain1
\n", 500 | "
" 501 | ], 502 | "text/plain": [ 503 | " img_folder img_filename ... split annotated\n", 504 | "id ... \n", 505 | "0 ../../images/train road23.png ... train 1\n", 506 | "1 ../../images/train road33.png ... train 1\n", 507 | "2 ../../images/train road8.png ... train 1\n", 508 | "3 ../../images/train road8.png ... train 1\n", 509 | "4 ../../images/train road16.png ... train 1\n", 510 | "\n", 511 | "[5 rows x 25 columns]" 512 | ] 513 | }, 514 | "metadata": {}, 515 | "execution_count": 10 516 | } 517 | ] 518 | }, 519 | { 520 | "cell_type": "code", 521 | "metadata": { 522 | "colab": { 523 | "base_uri": "https://localhost:8080/", 524 | "height": 195 525 | }, 526 | "id": "sUfbY-NxhhGn", 527 | "outputId": "8ac631dd-5dbd-4b94-bb42-ad6f44373624" 528 | }, 529 | "source": [ 530 | "#A sample of what the groupings look like\n", 531 | "data0.df.groupby('split').count()" 532 | ], 533 | "execution_count": 8, 534 | "outputs": [ 535 | { 536 | "output_type": "execute_result", 537 | "data": { 538 | "text/html": [ 539 | "
\n", 540 | "\n", 553 | "\n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | " \n", 629 | " \n", 630 | " \n", 631 | " \n", 632 | " \n", 633 | " \n", 634 | " \n", 635 | " \n", 636 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | " \n", 641 | " \n", 642 | " \n", 643 | " \n", 644 | " \n", 645 | " \n", 646 | " \n", 647 | " \n", 648 | " \n", 649 | " \n", 650 | " \n", 651 | " \n", 652 | " \n", 653 | " \n", 654 | " \n", 655 | " \n", 656 | " \n", 657 | " \n", 658 | " \n", 659 | " \n", 660 | " \n", 661 | " \n", 662 | " \n", 663 | " \n", 664 | " \n", 665 | " \n", 666 | " \n", 667 | " \n", 668 | " \n", 669 | " \n", 670 | " \n", 671 | " \n", 672 | " \n", 673 | " \n", 674 | " \n", 675 | " \n", 676 | " \n", 677 | " \n", 678 | " \n", 679 | " \n", 680 | " \n", 681 | " \n", 682 | " \n", 683 | " \n", 684 | " \n", 685 | " \n", 686 | " \n", 687 | " \n", 688 | " \n", 689 | " \n", 690 | " \n", 691 | " \n", 692 | " \n", 693 | "
img_folderimg_filenameimg_pathimg_idimg_widthimg_heightimg_depthann_segmentedann_bbox_xminann_bbox_yminann_bbox_xmaxann_bbox_ymaxann_bbox_widthann_bbox_heightann_areaann_segmentationann_iscrowdann_poseann_truncatedann_difficultcat_idcat_namecat_supercategoryannotated
split
test880888808888888000008808
train5555055555555055555555555555000005555055
val770777707777777000007707
\n", 694 | "
" 695 | ], 696 | "text/plain": [ 697 | " img_folder img_filename ... cat_supercategory annotated\n", 698 | "split ... \n", 699 | "test 8 8 ... 0 8\n", 700 | "train 55 55 ... 0 55\n", 701 | "val 7 7 ... 0 7\n", 702 | "\n", 703 | "[3 rows x 24 columns]" 704 | ] 705 | }, 706 | "metadata": {}, 707 | "execution_count": 8 708 | } 709 | ] 710 | }, 711 | { 712 | "cell_type": "code", 713 | "metadata": { 714 | "id": "AEuFW-vZhhA9" 715 | }, 716 | "source": [ 717 | "" 718 | ], 719 | "execution_count": null, 720 | "outputs": [] 721 | }, 722 | { 723 | "cell_type": "code", 724 | "metadata": { 725 | "id": "PUISOppWhg7x" 726 | }, 727 | "source": [ 728 | "" 729 | ], 730 | "execution_count": null, 731 | "outputs": [] 732 | }, 733 | { 734 | "cell_type": "code", 735 | "metadata": { 736 | "id": "UNXcq-QFhg5t" 737 | }, 738 | "source": [ 739 | "" 740 | ], 741 | "execution_count": null, 742 | "outputs": [] 743 | }, 744 | { 745 | "cell_type": "code", 746 | "metadata": { 747 | "id": "maPU3HdE5Hj6" 748 | }, 749 | "source": [ 750 | "" 751 | ], 752 | "execution_count": null, 753 | "outputs": [] 754 | }, 755 | { 756 | "cell_type": "code", 757 | "metadata": { 758 | "id": "3NyTds8a9sLw" 759 | }, 760 | "source": [ 761 | "" 762 | ], 763 | "execution_count": null, 764 | "outputs": [] 765 | }, 766 | { 767 | "cell_type": "code", 768 | "metadata": { 769 | "id": "68jpf37TnHlX" 770 | }, 771 | "source": [ 772 | "" 773 | ], 774 | "execution_count": null, 775 | "outputs": [] 776 | } 777 | ] 778 | } 779 | -------------------------------------------------------------------------------- /yolov5_training.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "accelerator": "GPU", 6 | "colab": { 7 | "name": "pylabeler.ipynb", 8 | "provenance": [], 9 | "collapsed_sections": [] 10 | }, 11 | "interpreter": { 12 | "hash": "de5e368ab5494158da905fb8b1c2e4fef8844fbfaace7cceca0beab983df3a80" 13 | }, 14 | "kernelspec": { 15 | "display_name": "Python 3.8.5 64-bit ('penv': venv)", 16 | "name": "python3" 17 | }, 18 | "language_info": { 19 | "codemirror_mode": { 20 | "name": "ipython", 21 | "version": 3 22 | }, 23 | "file_extension": ".py", 24 | "mimetype": "text/x-python", 25 | "name": "python", 26 | "nbconvert_exporter": "python", 27 | "pygments_lexer": "ipython3", 28 | "version": "3.8.5" 29 | } 30 | }, 31 | "cells": [ 32 | { 33 | "cell_type": "markdown", 34 | "metadata": { 35 | "id": "5UDUKQvj-I_j" 36 | }, 37 | "source": [ 38 | "\"Open " 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": { 44 | "id": "Cxi8K9mXwl5t" 45 | }, 46 | "source": [ 47 | "## Simple YoloV5 Training Example\n", 48 | "This notebook demonstrates how to use your own labeled dataset to train a YoloV5 model and then use it to make predictions. For this demonstration we will download 100 images from the squirrels and nuts dataset. (Which I created from images of squirrels in my yard.)\n" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "metadata": { 54 | "id": "_NcGRjmC-I_m" 55 | }, 56 | "source": [ 57 | "import logging\n", 58 | "logging.getLogger().setLevel(logging.CRITICAL)\n", 59 | "import os \n", 60 | "import zipfile" 61 | ], 62 | "execution_count": 1, 63 | "outputs": [] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": { 68 | "id": "dkFFxJFn-I_m" 69 | }, 70 | "source": [ 71 | "## Download Images and Labels" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "metadata": { 77 | "colab": { 78 | "base_uri": "https://localhost:8080/" 79 | }, 80 | "id": "dvT4Ykxb-I_n", 81 | "outputId": "ddf2e748-2e2f-40f2-a3ab-ae882687a506" 82 | }, 83 | "source": [ 84 | "os.makedirs(\"data/\", exist_ok=True)\n", 85 | "!wget \"https://github.com/pylabel-project/datasets_models/blob/main/squirrelsandnuts/squirrelsandnuts_train.zip?raw=true\" -O data/squirrelsandnuts_train.zip\n", 86 | "with zipfile.ZipFile(\"data/squirrelsandnuts_train.zip\", 'r') as zip_ref:\n", 87 | " zip_ref.extractall(\"data/\")" 88 | ], 89 | "execution_count": 2, 90 | "outputs": [ 91 | { 92 | "output_type": "stream", 93 | "name": "stdout", 94 | "text": [ 95 | "--2021-12-07 04:42:36-- https://github.com/pylabel-project/datasets_models/blob/main/squirrelsandnuts/squirrelsandnuts_train.zip?raw=true\n", 96 | "Resolving github.com (github.com)... 140.82.121.3\n", 97 | "Connecting to github.com (github.com)|140.82.121.3|:443... connected.\n", 98 | "HTTP request sent, awaiting response... 302 Found\n", 99 | "Location: https://github.com/pylabel-project/datasets_models/raw/main/squirrelsandnuts/squirrelsandnuts_train.zip [following]\n", 100 | "--2021-12-07 04:42:36-- https://github.com/pylabel-project/datasets_models/raw/main/squirrelsandnuts/squirrelsandnuts_train.zip\n", 101 | "Reusing existing connection to github.com:443.\n", 102 | "HTTP request sent, awaiting response... 302 Found\n", 103 | "Location: https://raw.githubusercontent.com/pylabel-project/datasets_models/main/squirrelsandnuts/squirrelsandnuts_train.zip [following]\n", 104 | "--2021-12-07 04:42:37-- https://raw.githubusercontent.com/pylabel-project/datasets_models/main/squirrelsandnuts/squirrelsandnuts_train.zip\n", 105 | "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.110.133, ...\n", 106 | "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", 107 | "HTTP request sent, awaiting response... 200 OK\n", 108 | "Length: 10368708 (9.9M) [application/zip]\n", 109 | "Saving to: ‘data/squirrelsandnuts_train.zip’\n", 110 | "\n", 111 | "data/squirrelsandnu 100%[===================>] 9.89M --.-KB/s in 0.1s \n", 112 | "\n", 113 | "2021-12-07 04:42:37 (96.5 MB/s) - ‘data/squirrelsandnuts_train.zip’ saved [10368708/10368708]\n", 114 | "\n" 115 | ] 116 | } 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": { 122 | "id": "OO6wuzVuaXO3" 123 | }, 124 | "source": [ 125 | "Now you should have 100 images and annotation files in the folder data/squirrelsandnuts_train/. There is also a YAML file that you need to tell YOLO where to find the images and folders. View the Yaml file. Note that there are 2 classes: squirrels and nuts. " 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "metadata": { 131 | "id": "i-PP611TbBRD", 132 | "outputId": "592f1f68-a411-4488-9657-5348b60be286", 133 | "colab": { 134 | "base_uri": "https://localhost:8080/" 135 | } 136 | }, 137 | "source": [ 138 | "!cat data/squirrelsandnuts_train/yolo_data.yaml" 139 | ], 140 | "execution_count": 3, 141 | "outputs": [ 142 | { 143 | "output_type": "stream", 144 | "name": "stdout", 145 | "text": [ 146 | "path: ../data/squirrelsandnuts_train/\n", 147 | "train: images/train # train images (relative to 'path') 128 images\n", 148 | "val: images/train # val images (relative to 'path') 128 images\n", 149 | "\n", 150 | "# Classes\n", 151 | "nc: 2 # number of classes\n", 152 | "names: [ 'Squirrel','Nut'] # class names" 153 | ] 154 | } 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": { 160 | "id": "rlVIf5qj-I_o" 161 | }, 162 | "source": [ 163 | "# Install Yolo Dependencies\n", 164 | "This is known to work on Google Colab, it may or may not work in other environments. " 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "metadata": { 170 | "colab": { 171 | "base_uri": "https://localhost:8080/" 172 | }, 173 | "id": "1-EeN4ZX-I_o", 174 | "outputId": "79e8966c-8210-4d6f-cdd1-30eebe56e96a" 175 | }, 176 | "source": [ 177 | "!git clone https://github.com/ultralytics/yolov5 # clone\n", 178 | "%cd yolov5\n", 179 | "%pip install -qr requirements.txt # install\n", 180 | "import torch\n", 181 | "from yolov5 import utils" 182 | ], 183 | "execution_count": 4, 184 | "outputs": [ 185 | { 186 | "output_type": "stream", 187 | "name": "stdout", 188 | "text": [ 189 | "fatal: destination path 'yolov5' already exists and is not an empty directory.\n", 190 | "/content/yolov5\n" 191 | ] 192 | } 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": { 198 | "id": "kCL9U0lHOnuB" 199 | }, 200 | "source": [ 201 | "Now you are ready to train the model. Below is the standard code that is used for training which I customized for this particulat dataset. Some of the key parameters: \n", 202 | "- **img** This should be the longest dimension of your images in pixels. The squirrel photos are 960 pixels wide.\n", 203 | "- **data** The path to the yaml file, from the yolov5 directory. \n", 204 | "- **weights** Start from the standard yolo pretraining model. \n", 205 | "- **epochs** It is set to 10 so it goes faster while you are still testing things. I would suggest doing at least 100 epochs for your actual model training. " 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "metadata": { 211 | "colab": { 212 | "base_uri": "https://localhost:8080/" 213 | }, 214 | "id": "_ulnXfSqU9A5", 215 | "outputId": "760da9fd-e364-4599-d9ed-c9fbe6ddbb1a" 216 | }, 217 | "source": [ 218 | "!python train.py --img 960 --batch 16 --epochs 10 --data ../data/squirrelsandnuts_train/yolo_data.yaml --weights yolov5s.pt --cache --exist-ok\n" 219 | ], 220 | "execution_count": 5, 221 | "outputs": [ 222 | { 223 | "output_type": "stream", 224 | "name": "stdout", 225 | "text": [ 226 | "\u001b[34m\u001b[1mtrain: \u001b[0mweights=yolov5s.pt, cfg=, data=../data/squirrelsandnuts_train/yolo_data.yaml, hyp=data/hyps/hyp.scratch.yaml, epochs=10, batch_size=16, imgsz=960, rect=False, resume=False, nosave=False, noval=False, noautoanchor=False, evolve=None, bucket=, cache=ram, image_weights=False, device=, multi_scale=False, single_cls=False, adam=False, sync_bn=False, workers=8, project=runs/train, name=exp, exist_ok=True, quad=False, linear_lr=False, label_smoothing=0.0, patience=100, freeze=0, save_period=-1, local_rank=-1, entity=None, upload_dataset=False, bbox_interval=-1, artifact_alias=latest\n", 227 | "\u001b[34m\u001b[1mgithub: \u001b[0mup to date with https://github.com/ultralytics/yolov5 ✅\n", 228 | "YOLOv5 🚀 v6.0-124-g1075488 torch 1.10.0+cu111 CUDA:0 (Tesla K80, 11441MiB)\n", 229 | "\n", 230 | "\u001b[34m\u001b[1mhyperparameters: \u001b[0mlr0=0.01, lrf=0.1, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=0.05, cls=0.5, cls_pw=1.0, obj=1.0, obj_pw=1.0, iou_t=0.2, anchor_t=4.0, fl_gamma=0.0, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0\n", 231 | "\u001b[34m\u001b[1mWeights & Biases: \u001b[0mrun 'pip install wandb' to automatically track and visualize YOLOv5 🚀 runs (RECOMMENDED)\n", 232 | "\u001b[34m\u001b[1mTensorBoard: \u001b[0mStart with 'tensorboard --logdir runs/train', view at http://localhost:6006/\n", 233 | "Overriding model.yaml nc=80 with nc=2\n", 234 | "\n", 235 | " from n params module arguments \n", 236 | " 0 -1 1 3520 models.common.Conv [3, 32, 6, 2, 2] \n", 237 | " 1 -1 1 18560 models.common.Conv [32, 64, 3, 2] \n", 238 | " 2 -1 1 18816 models.common.C3 [64, 64, 1] \n", 239 | " 3 -1 1 73984 models.common.Conv [64, 128, 3, 2] \n", 240 | " 4 -1 2 115712 models.common.C3 [128, 128, 2] \n", 241 | " 5 -1 1 295424 models.common.Conv [128, 256, 3, 2] \n", 242 | " 6 -1 3 625152 models.common.C3 [256, 256, 3] \n", 243 | " 7 -1 1 1180672 models.common.Conv [256, 512, 3, 2] \n", 244 | " 8 -1 1 1182720 models.common.C3 [512, 512, 1] \n", 245 | " 9 -1 1 656896 models.common.SPPF [512, 512, 5] \n", 246 | " 10 -1 1 131584 models.common.Conv [512, 256, 1, 1] \n", 247 | " 11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] \n", 248 | " 12 [-1, 6] 1 0 models.common.Concat [1] \n", 249 | " 13 -1 1 361984 models.common.C3 [512, 256, 1, False] \n", 250 | " 14 -1 1 33024 models.common.Conv [256, 128, 1, 1] \n", 251 | " 15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] \n", 252 | " 16 [-1, 4] 1 0 models.common.Concat [1] \n", 253 | " 17 -1 1 90880 models.common.C3 [256, 128, 1, False] \n", 254 | " 18 -1 1 147712 models.common.Conv [128, 128, 3, 2] \n", 255 | " 19 [-1, 14] 1 0 models.common.Concat [1] \n", 256 | " 20 -1 1 296448 models.common.C3 [256, 256, 1, False] \n", 257 | " 21 -1 1 590336 models.common.Conv [256, 256, 3, 2] \n", 258 | " 22 [-1, 10] 1 0 models.common.Concat [1] \n", 259 | " 23 -1 1 1182720 models.common.C3 [512, 512, 1, False] \n", 260 | " 24 [17, 20, 23] 1 18879 models.yolo.Detect [2, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]]\n", 261 | "Model Summary: 270 layers, 7025023 parameters, 7025023 gradients, 15.9 GFLOPs\n", 262 | "\n", 263 | "Transferred 343/349 items from yolov5s.pt\n", 264 | "Scaled weight_decay = 0.0005\n", 265 | "\u001b[34m\u001b[1moptimizer:\u001b[0m SGD with parameter groups 57 weight, 60 weight (no decay), 60 bias\n", 266 | "\u001b[34m\u001b[1malbumentations: \u001b[0mversion 1.0.3 required by YOLOv5, but version 0.1.12 is currently installed\n", 267 | "\u001b[34m\u001b[1mtrain: \u001b[0mScanning '../data/squirrelsandnuts_train/labels/train.cache' images and labels... 100 found, 0 missing, 0 empty, 0 corrupted: 100% 100/100 [00:00\n", 396 | "\n", 409 | "\n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | "
xminyminxmaxymaxconfidenceclassname
\n", 425 | "" 426 | ], 427 | "text/plain": [ 428 | "Empty DataFrame\n", 429 | "Columns: [xmin, ymin, xmax, ymax, confidence, class, name]\n", 430 | "Index: []" 431 | ] 432 | }, 433 | "metadata": {}, 434 | "execution_count": 6 435 | } 436 | ] 437 | }, 438 | { 439 | "cell_type": "markdown", 440 | "metadata": { 441 | "id": "FwHyG9WdKX8o" 442 | }, 443 | "source": [ 444 | "Look at the output above. Look in the runs/detect folder. If there are no classes detected then the model is not working well and you need more data, more epochs, or to try other things. " 445 | ] 446 | } 447 | ] 448 | } --------------------------------------------------------------------------------