mirror of
https://github.com/THU-MIG/yolov10.git
synced 2025-05-23 21:44:22 +08:00
Fix HUBDatasetStats for no-label edge cases (#4583)
This commit is contained in:
parent
2db35afad5
commit
f755ba88c3
@ -93,10 +93,14 @@ If you have your own dataset and would like to use it for training detection mod
|
|||||||
|
|
||||||
You can easily convert labels from the popular COCO dataset format to the YOLO format using the following code snippet:
|
You can easily convert labels from the popular COCO dataset format to the YOLO format using the following code snippet:
|
||||||
|
|
||||||
|
!!! example ""
|
||||||
|
|
||||||
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ultralytics.data.converter import convert_coco
|
from ultralytics.data.converter import convert_coco
|
||||||
|
|
||||||
convert_coco(labels_dir='../coco/annotations/')
|
convert_coco(labels_dir='path/to/coco/annotations/')
|
||||||
```
|
```
|
||||||
|
|
||||||
This conversion tool can be used to convert the COCO dataset or any dataset in the COCO format to the Ultralytics YOLO format.
|
This conversion tool can be used to convert the COCO dataset or any dataset in the COCO format to the Ultralytics YOLO format.
|
||||||
|
@ -69,6 +69,10 @@ For those looking to introduce their own datasets with oriented bounding boxes,
|
|||||||
|
|
||||||
Transitioning labels from the DOTA dataset format to the YOLO OBB format can be achieved with this script:
|
Transitioning labels from the DOTA dataset format to the YOLO OBB format can be achieved with this script:
|
||||||
|
|
||||||
|
!!! example ""
|
||||||
|
|
||||||
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ultralytics.data.converter import convert_dota_to_yolo_obb
|
from ultralytics.data.converter import convert_dota_to_yolo_obb
|
||||||
|
|
||||||
|
@ -10,9 +10,7 @@ keywords: Ultralytics, YOLO, pose estimation, datasets, training, YAML, keypoint
|
|||||||
|
|
||||||
### Ultralytics YOLO format
|
### Ultralytics YOLO format
|
||||||
|
|
||||||
** Label Format **
|
The dataset label format used for training YOLO pose models is as follows:
|
||||||
|
|
||||||
The dataset format used for training YOLO pose models is as follows:
|
|
||||||
|
|
||||||
1. One text file per image: Each image in the dataset has a corresponding text file with the same name as the image file and the ".txt" extension.
|
1. One text file per image: Each image in the dataset has a corresponding text file with the same name as the image file and the ".txt" extension.
|
||||||
2. One row per object: Each row in the text file corresponds to one object instance in the image.
|
2. One row per object: Each row in the text file corresponds to one object instance in the image.
|
||||||
@ -119,10 +117,14 @@ If you have your own dataset and would like to use it for training pose estimati
|
|||||||
|
|
||||||
Ultralytics provides a convenient conversion tool to convert labels from the popular COCO dataset format to YOLO format:
|
Ultralytics provides a convenient conversion tool to convert labels from the popular COCO dataset format to YOLO format:
|
||||||
|
|
||||||
|
!!! example ""
|
||||||
|
|
||||||
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ultralytics.data.converter import convert_coco
|
from ultralytics.data.converter import convert_coco
|
||||||
|
|
||||||
convert_coco(labels_dir='../coco/annotations/', use_keypoints=True)
|
convert_coco(labels_dir='path/to/coco/annotations/', use_keypoints=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
This conversion tool can be used to convert the COCO dataset or any dataset in the COCO format to the Ultralytics YOLO format. The `use_keypoints` parameter specifies whether to include keypoints (for pose estimation) in the converted labels.
|
This conversion tool can be used to convert the COCO dataset or any dataset in the COCO format to the Ultralytics YOLO format. The `use_keypoints` parameter specifies whether to include keypoints (for pose estimation) in the converted labels.
|
||||||
|
@ -10,9 +10,7 @@ keywords: Ultralytics, YOLO, Instance Segmentation, Dataset, YAML, COCO, Auto-An
|
|||||||
|
|
||||||
### Ultralytics YOLO format
|
### Ultralytics YOLO format
|
||||||
|
|
||||||
** Label Format **
|
The dataset label format used for training YOLO segmentation models is as follows:
|
||||||
|
|
||||||
The dataset format used for training YOLO segmentation models is as follows:
|
|
||||||
|
|
||||||
1. One text file per image: Each image in the dataset has a corresponding text file with the same name as the image file and the ".txt" extension.
|
1. One text file per image: Each image in the dataset has a corresponding text file with the same name as the image file and the ".txt" extension.
|
||||||
2. One row per object: Each row in the text file corresponds to one object instance in the image.
|
2. One row per object: Each row in the text file corresponds to one object instance in the image.
|
||||||
@ -28,16 +26,16 @@ The format for a single row in the segmentation dataset file is as follows:
|
|||||||
|
|
||||||
In this format, `<class-index>` is the index of the class for the object, and `<x1> <y1> <x2> <y2> ... <xn> <yn>` are the bounding coordinates of the object's segmentation mask. The coordinates are separated by spaces.
|
In this format, `<class-index>` is the index of the class for the object, and `<x1> <y1> <x2> <y2> ... <xn> <yn>` are the bounding coordinates of the object's segmentation mask. The coordinates are separated by spaces.
|
||||||
|
|
||||||
Here is an example of the YOLO dataset format for a single image with two object instances:
|
Here is an example of the YOLO dataset format for a single image with two objects made up of a 3-point segment and a 5-point segment.
|
||||||
|
|
||||||
```
|
```
|
||||||
0 0.6812 0.48541 0.67 0.4875 0.67656 0.487 0.675 0.489 0.66
|
0 0.681 0.485 0.670 0.487 0.676 0.487
|
||||||
1 0.5046 0.0 0.5015 0.004 0.4984 0.00416 0.4937 0.010 0.492 0.0104
|
1 0.504 0.000 0.501 0.004 0.498 0.004 0.493 0.010 0.492 0.0104
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tip "Tip"
|
!!! tip "Tip"
|
||||||
|
|
||||||
- The length of each row does not have to be equal.
|
- The length of each row does **not** have to be equal.
|
||||||
- Each segmentation label must have a **minimum of 3 xy points**: `<class-index> <x1> <y1> <x2> <y2> <x3> <y3>`
|
- Each segmentation label must have a **minimum of 3 xy points**: `<class-index> <x1> <y1> <x2> <y2> <x3> <y3>`
|
||||||
|
|
||||||
### Dataset YAML format
|
### Dataset YAML format
|
||||||
@ -103,10 +101,14 @@ If you have your own dataset and would like to use it for training segmentation
|
|||||||
|
|
||||||
You can easily convert labels from the popular COCO dataset format to the YOLO format using the following code snippet:
|
You can easily convert labels from the popular COCO dataset format to the YOLO format using the following code snippet:
|
||||||
|
|
||||||
|
!!! example ""
|
||||||
|
|
||||||
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ultralytics.data.converter import convert_coco
|
from ultralytics.data.converter import convert_coco
|
||||||
|
|
||||||
convert_coco(labels_dir='../coco/annotations/', use_segments=True)
|
convert_coco(labels_dir='path/to/coco/annotations/', use_segments=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
This conversion tool can be used to convert the COCO dataset or any dataset in the COCO format to the Ultralytics YOLO format.
|
This conversion tool can be used to convert the COCO dataset or any dataset in the COCO format to the Ultralytics YOLO format.
|
||||||
@ -121,6 +123,10 @@ Auto-annotation is an essential feature that allows you to generate a segmentati
|
|||||||
|
|
||||||
To auto-annotate your dataset using the Ultralytics framework, you can use the `auto_annotate` function as shown below:
|
To auto-annotate your dataset using the Ultralytics framework, you can use the `auto_annotate` function as shown below:
|
||||||
|
|
||||||
|
!!! example ""
|
||||||
|
|
||||||
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ultralytics.data.annotator import auto_annotate
|
from ultralytics.data.annotator import auto_annotate
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ Below are code examples for using each source type:
|
|||||||
```
|
```
|
||||||
|
|
||||||
=== "Streams"
|
=== "Streams"
|
||||||
Run inference on remote streaming sources using RTSP, RTMP, and IP address protocols. If mutliple streams are provided in a `*.streams` text file then batched inference will run, i.e. 8 streams will run at batch-size 8, otherwise single streams will run at batch-size 1.
|
Run inference on remote streaming sources using RTSP, RTMP, and IP address protocols. If multiple streams are provided in a `*.streams` text file then batched inference will run, i.e. 8 streams will run at batch-size 8, otherwise single streams will run at batch-size 1.
|
||||||
```python
|
```python
|
||||||
from ultralytics import YOLO
|
from ultralytics import YOLO
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ Ultralytics provides various installation methods including pip, conda, and Dock
|
|||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
|
|
||||||
If you are installing in a CUDA environment best practice is to install `ultralytics`, `pytorch` and `pytorch-cuda` in the same command to allow the conda package manager to resolve any conflicts, or else to install `pytorch-cuda` last to allow it override the CPU-specific `pytorch` package if necesary.
|
If you are installing in a CUDA environment best practice is to install `ultralytics`, `pytorch` and `pytorch-cuda` in the same command to allow the conda package manager to resolve any conflicts, or else to install `pytorch-cuda` last to allow it override the CPU-specific `pytorch` package if necessary.
|
||||||
```bash
|
```bash
|
||||||
# Install all packages together using conda
|
# Install all packages together using conda
|
||||||
conda install -c conda-forge -c pytorch -c nvidia ultralytics pytorch torchvision pytorch-cuda=11.8
|
conda install -c conda-forge -c pytorch -c nvidia ultralytics pytorch torchvision pytorch-cuda=11.8
|
||||||
|
2
setup.py
2
setup.py
@ -47,7 +47,7 @@ setup(
|
|||||||
'mkdocs-material',
|
'mkdocs-material',
|
||||||
'mkdocstrings[python]',
|
'mkdocstrings[python]',
|
||||||
'mkdocs-redirects', # for 301 redirects
|
'mkdocs-redirects', # for 301 redirects
|
||||||
'mkdocs-ultralytics-plugin>=0.0.25', # for meta descriptions and images, dates and authors
|
'mkdocs-ultralytics-plugin>=0.0.26', # for meta descriptions and images, dates and authors
|
||||||
],
|
],
|
||||||
'export': [
|
'export': [
|
||||||
'coremltools>=7.0.b1',
|
'coremltools>=7.0.b1',
|
||||||
|
@ -115,7 +115,7 @@ class BaseDataset(Dataset):
|
|||||||
raise FileNotFoundError(f'{self.prefix}{p} does not exist')
|
raise FileNotFoundError(f'{self.prefix}{p} does not exist')
|
||||||
im_files = sorted(x.replace('/', os.sep) for x in f if x.split('.')[-1].lower() in IMG_FORMATS)
|
im_files = sorted(x.replace('/', os.sep) for x in f if x.split('.')[-1].lower() in IMG_FORMATS)
|
||||||
# self.img_files = sorted([x for x in f if x.suffix[1:].lower() in IMG_FORMATS]) # pathlib
|
# self.img_files = sorted([x for x in f if x.suffix[1:].lower() in IMG_FORMATS]) # pathlib
|
||||||
assert im_files, f'{self.prefix}No images found'
|
assert im_files, f'{self.prefix}No images found in {img_path}'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise FileNotFoundError(f'{self.prefix}Error loading data from {img_path}\n{HELP_URL}') from e
|
raise FileNotFoundError(f'{self.prefix}Error loading data from {img_path}\n{HELP_URL}') from e
|
||||||
if self.fraction < 1:
|
if self.fraction < 1:
|
||||||
|
@ -110,13 +110,12 @@ class YOLODataset(BaseDataset):
|
|||||||
tqdm(None, desc=self.prefix + d, total=n, initial=n, bar_format=TQDM_BAR_FORMAT) # display results
|
tqdm(None, desc=self.prefix + d, total=n, initial=n, bar_format=TQDM_BAR_FORMAT) # display results
|
||||||
if cache['msgs']:
|
if cache['msgs']:
|
||||||
LOGGER.info('\n'.join(cache['msgs'])) # display warnings
|
LOGGER.info('\n'.join(cache['msgs'])) # display warnings
|
||||||
if nf == 0: # number of labels found
|
|
||||||
raise FileNotFoundError(f'{self.prefix}No labels found in {cache_path}, can not start training. {HELP_URL}')
|
|
||||||
|
|
||||||
# Read cache
|
# Read cache
|
||||||
[cache.pop(k) for k in ('hash', 'version', 'msgs')] # remove items
|
[cache.pop(k) for k in ('hash', 'version', 'msgs')] # remove items
|
||||||
labels = cache['labels']
|
labels = cache['labels']
|
||||||
assert len(labels), f'No valid labels found, please check your dataset. {HELP_URL}'
|
if not labels:
|
||||||
|
LOGGER.warning(f'WARNING ⚠️ No images found in {cache_path}, training may not work correctly. {HELP_URL}')
|
||||||
self.im_files = [lb['im_file'] for lb in labels] # update im_files
|
self.im_files = [lb['im_file'] for lb in labels] # update im_files
|
||||||
|
|
||||||
# Check if the dataset is all boxes or all segments
|
# Check if the dataset is all boxes or all segments
|
||||||
@ -130,10 +129,9 @@ class YOLODataset(BaseDataset):
|
|||||||
for lb in labels:
|
for lb in labels:
|
||||||
lb['segments'] = []
|
lb['segments'] = []
|
||||||
if len_cls == 0:
|
if len_cls == 0:
|
||||||
raise ValueError(f'All labels empty in {cache_path}, can not start training without labels. {HELP_URL}')
|
LOGGER.warning(f'WARNING ⚠️ No labels found in {cache_path}, training may not work correctly. {HELP_URL}')
|
||||||
return labels
|
return labels
|
||||||
|
|
||||||
# TODO: use hyp config to set all these augmentations
|
|
||||||
def build_transforms(self, hyp=None):
|
def build_transforms(self, hyp=None):
|
||||||
"""Builds and appends transforms to the list."""
|
"""Builds and appends transforms to the list."""
|
||||||
if self.augment:
|
if self.augment:
|
||||||
|
@ -447,10 +447,17 @@ class HUBDatasetStats:
|
|||||||
return [[int(c[0]), *(round(float(x), 4) for x in points)] for c, points in zipped]
|
return [[int(c[0]), *(round(float(x), 4) for x in points)] for c, points in zipped]
|
||||||
|
|
||||||
for split in 'train', 'val', 'test':
|
for split in 'train', 'val', 'test':
|
||||||
if self.data.get(split) is None:
|
self.stats[split] = None # predefine
|
||||||
self.stats[split] = None # i.e. no test set
|
path = self.data.get(split)
|
||||||
|
|
||||||
|
# Check split
|
||||||
|
if path is None: # no split
|
||||||
|
continue
|
||||||
|
files = [f for f in Path(path).rglob('*.*') if f.suffix[1:].lower() in IMG_FORMATS] # image files in split
|
||||||
|
if not files: # no images
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Get dataset statistics
|
||||||
dataset = YOLODataset(img_path=self.data[split],
|
dataset = YOLODataset(img_path=self.data[split],
|
||||||
data=self.data,
|
data=self.data,
|
||||||
use_segments=self.task == 'segment',
|
use_segments=self.task == 'segment',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user