ultralytics 8.0.98__tar.gz → 8.0.100__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ultralytics might be problematic. Click here for more details.
- {ultralytics-8.0.98/ultralytics.egg-info → ultralytics-8.0.100}/PKG-INFO +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/requirements.txt +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/setup.py +1 -2
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/__init__.py +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/modules/block.py +2 -2
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/tasks.py +2 -2
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/trackers/byte_tracker.py +6 -6
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/rtdetr/model.py +10 -2
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/build.py +5 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/model.py +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/augment.py +76 -16
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/model.py +3 -2
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/trainer.py +9 -4
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/checks.py +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/loss.py +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/tal.py +1 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/torch_utils.py +3 -2
- {ultralytics-8.0.98 → ultralytics-8.0.100/ultralytics.egg-info}/PKG-INFO +1 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics.egg-info/requires.txt +0 -1
- {ultralytics-8.0.98 → ultralytics-8.0.100}/CONTRIBUTING.md +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/LICENSE +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/MANIFEST.in +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/README.md +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/README.zh-CN.md +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/setup.cfg +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/tests/test_cli.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/tests/test_engine.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/tests/test_python.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/assets/bus.jpg +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/assets/zidane.jpg +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/Argoverse.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/GlobalWheat2020.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/ImageNet.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/Objects365.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/SKU-110K.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/VOC.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/VisDrone.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco-pose.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco128-seg.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco128.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco8-pose.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco8-seg.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/coco8.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/datasets/xView.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/hub/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/hub/auth.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/hub/session.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/hub/utils.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/rt-detr/rt-detr-l.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/rt-detr/rt-detr-x.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v3/yolov3-spp.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v3/yolov3-tiny.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v3/yolov3.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v5/yolov5-p6.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v5/yolov5.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8-cls.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8-p2.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8-p6.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8-pose-p6.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8-pose.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8-seg.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/models/v8/yolov8.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/autobackend.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/autoshape.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/modules/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/modules/conv.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/modules/head.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/modules/transformer.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/nn/modules/utils.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/cfg/botsort.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/cfg/bytetrack.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/track.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/trackers/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/trackers/basetrack.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/trackers/bot_sort.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/utils/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/utils/gmc.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/utils/kalman_filter.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/tracker/utils/matching.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/rtdetr/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/rtdetr/predict.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/rtdetr/val.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/amg.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/autosize.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/decoders.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/encoders.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/mask_generator.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/prompt_predictor.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/sam.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/modules/transformer.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/vit/sam/predict.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/cfg/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/cfg/default.yaml +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/annotator.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/base.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/build.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/converter.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataloaders/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataloaders/stream_loaders.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataloaders/v5augmentations.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataloaders/v5loader.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataset.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataset_wrappers.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/utils.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/exporter.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/predictor.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/results.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/engine/validator.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/autobatch.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/benchmarks.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/base.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/clearml.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/comet.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/hub.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/mlflow.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/neptune.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/raytune.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/tensorboard.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/callbacks/wb.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/dist.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/downloads.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/errors.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/files.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/instance.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/metrics.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/ops.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/plotting.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/utils/tuner.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/classify/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/classify/predict.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/classify/train.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/classify/val.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/detect/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/detect/predict.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/detect/train.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/detect/val.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/pose/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/pose/predict.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/pose/train.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/pose/val.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/segment/__init__.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/segment/predict.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/segment/train.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/v8/segment/val.py +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics.egg-info/SOURCES.txt +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics.egg-info/dependency_links.txt +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics.egg-info/entry_points.txt +0 -0
- {ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ultralytics
|
|
3
|
-
Version: 8.0.
|
|
3
|
+
Version: 8.0.100
|
|
4
4
|
Summary: Ultralytics YOLOv8 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
|
|
5
5
|
Home-page: https://github.com/ultralytics/ultralytics
|
|
6
6
|
Author: Ultralytics
|
|
@@ -47,8 +47,7 @@ setup(
|
|
|
47
47
|
'mkdocs-material',
|
|
48
48
|
'mkdocstrings[python]',
|
|
49
49
|
'mkdocs-redirects', # for 301 redirects
|
|
50
|
-
'mkdocs-
|
|
51
|
-
'mkdocs-ultralytics-plugin', # for meta descriptions and images
|
|
50
|
+
'mkdocs-ultralytics-plugin', # for meta descriptions and images, dates and authors
|
|
52
51
|
],
|
|
53
52
|
'export': ['coremltools>=6.0', 'openvino-dev>=2022.3', 'tensorflowjs'], # automatically installs tensorflow
|
|
54
53
|
},
|
|
@@ -177,13 +177,13 @@ class C2f(nn.Module):
|
|
|
177
177
|
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
|
|
178
178
|
|
|
179
179
|
def forward(self, x):
|
|
180
|
-
"""Forward pass
|
|
180
|
+
"""Forward pass through C2f layer."""
|
|
181
181
|
y = list(self.cv1(x).chunk(2, 1))
|
|
182
182
|
y.extend(m(y[-1]) for m in self.m)
|
|
183
183
|
return self.cv2(torch.cat(y, 1))
|
|
184
184
|
|
|
185
185
|
def forward_split(self, x):
|
|
186
|
-
"""
|
|
186
|
+
"""Forward pass using split() instead of chunk()."""
|
|
187
187
|
y = list(self.cv1(x).split((self.c, self.c), 1))
|
|
188
188
|
y.extend(m(y[-1]) for m in self.m)
|
|
189
189
|
return self.cv2(torch.cat(y, 1))
|
|
@@ -126,7 +126,7 @@ class BaseModel(nn.Module):
|
|
|
126
126
|
bn = tuple(v for k, v in nn.__dict__.items() if 'Norm' in k) # normalization layers, i.e. BatchNorm2d()
|
|
127
127
|
return sum(isinstance(v, bn) for v in self.modules()) < thresh # True if < 'thresh' BatchNorm layers in model
|
|
128
128
|
|
|
129
|
-
def info(self, verbose=True, imgsz=640):
|
|
129
|
+
def info(self, detailed=False, verbose=True, imgsz=640):
|
|
130
130
|
"""
|
|
131
131
|
Prints model information
|
|
132
132
|
|
|
@@ -134,7 +134,7 @@ class BaseModel(nn.Module):
|
|
|
134
134
|
verbose (bool): if True, prints out the model information. Defaults to False
|
|
135
135
|
imgsz (int): the size of the image that the model will be trained on. Defaults to 640
|
|
136
136
|
"""
|
|
137
|
-
model_info(self, verbose=verbose, imgsz=imgsz)
|
|
137
|
+
return model_info(self, detailed=detailed, verbose=verbose, imgsz=imgsz)
|
|
138
138
|
|
|
139
139
|
def _apply(self, fn):
|
|
140
140
|
"""
|
|
@@ -181,7 +181,7 @@ class BYTETracker:
|
|
|
181
181
|
def update(self, results, img=None):
|
|
182
182
|
"""Updates object tracker with new detections and returns tracked object bounding boxes."""
|
|
183
183
|
self.frame_id += 1
|
|
184
|
-
|
|
184
|
+
activated_stracks = []
|
|
185
185
|
refind_stracks = []
|
|
186
186
|
lost_stracks = []
|
|
187
187
|
removed_stracks = []
|
|
@@ -230,7 +230,7 @@ class BYTETracker:
|
|
|
230
230
|
det = detections[idet]
|
|
231
231
|
if track.state == TrackState.Tracked:
|
|
232
232
|
track.update(det, self.frame_id)
|
|
233
|
-
|
|
233
|
+
activated_stracks.append(track)
|
|
234
234
|
else:
|
|
235
235
|
track.re_activate(det, self.frame_id, new_id=False)
|
|
236
236
|
refind_stracks.append(track)
|
|
@@ -246,7 +246,7 @@ class BYTETracker:
|
|
|
246
246
|
det = detections_second[idet]
|
|
247
247
|
if track.state == TrackState.Tracked:
|
|
248
248
|
track.update(det, self.frame_id)
|
|
249
|
-
|
|
249
|
+
activated_stracks.append(track)
|
|
250
250
|
else:
|
|
251
251
|
track.re_activate(det, self.frame_id, new_id=False)
|
|
252
252
|
refind_stracks.append(track)
|
|
@@ -262,7 +262,7 @@ class BYTETracker:
|
|
|
262
262
|
matches, u_unconfirmed, u_detection = matching.linear_assignment(dists, thresh=0.7)
|
|
263
263
|
for itracked, idet in matches:
|
|
264
264
|
unconfirmed[itracked].update(detections[idet], self.frame_id)
|
|
265
|
-
|
|
265
|
+
activated_stracks.append(unconfirmed[itracked])
|
|
266
266
|
for it in u_unconfirmed:
|
|
267
267
|
track = unconfirmed[it]
|
|
268
268
|
track.mark_removed()
|
|
@@ -273,7 +273,7 @@ class BYTETracker:
|
|
|
273
273
|
if track.score < self.args.new_track_thresh:
|
|
274
274
|
continue
|
|
275
275
|
track.activate(self.kalman_filter, self.frame_id)
|
|
276
|
-
|
|
276
|
+
activated_stracks.append(track)
|
|
277
277
|
# Step 5: Update state
|
|
278
278
|
for track in self.lost_stracks:
|
|
279
279
|
if self.frame_id - track.end_frame > self.max_time_lost:
|
|
@@ -281,7 +281,7 @@ class BYTETracker:
|
|
|
281
281
|
removed_stracks.append(track)
|
|
282
282
|
|
|
283
283
|
self.tracked_stracks = [t for t in self.tracked_stracks if t.state == TrackState.Tracked]
|
|
284
|
-
self.tracked_stracks = self.joint_stracks(self.tracked_stracks,
|
|
284
|
+
self.tracked_stracks = self.joint_stracks(self.tracked_stracks, activated_stracks)
|
|
285
285
|
self.tracked_stracks = self.joint_stracks(self.tracked_stracks, refind_stracks)
|
|
286
286
|
self.lost_stracks = self.sub_stracks(self.lost_stracks, self.tracked_stracks)
|
|
287
287
|
self.lost_stracks.extend(lost_stracks)
|
|
@@ -8,8 +8,9 @@ from pathlib import Path
|
|
|
8
8
|
from ultralytics.nn.tasks import DetectionModel, attempt_load_one_weight, yaml_model_load
|
|
9
9
|
from ultralytics.yolo.cfg import get_cfg
|
|
10
10
|
from ultralytics.yolo.engine.exporter import Exporter
|
|
11
|
-
from ultralytics.yolo.utils import DEFAULT_CFG, DEFAULT_CFG_DICT
|
|
11
|
+
from ultralytics.yolo.utils import DEFAULT_CFG, DEFAULT_CFG_DICT, LOGGER, ROOT, is_git_dir
|
|
12
12
|
from ultralytics.yolo.utils.checks import check_imgsz
|
|
13
|
+
from ultralytics.yolo.utils.torch_utils import model_info
|
|
13
14
|
|
|
14
15
|
from ...yolo.utils.torch_utils import smart_inference_mode
|
|
15
16
|
from .predict import RTDETRPredictor
|
|
@@ -46,7 +47,7 @@ class RTDETR:
|
|
|
46
47
|
self.task = self.model.args['task']
|
|
47
48
|
|
|
48
49
|
@smart_inference_mode()
|
|
49
|
-
def predict(self, source, stream=False, **kwargs):
|
|
50
|
+
def predict(self, source=None, stream=False, **kwargs):
|
|
50
51
|
"""
|
|
51
52
|
Perform prediction using the YOLO model.
|
|
52
53
|
|
|
@@ -60,6 +61,9 @@ class RTDETR:
|
|
|
60
61
|
Returns:
|
|
61
62
|
(List[ultralytics.yolo.engine.results.Results]): The prediction results.
|
|
62
63
|
"""
|
|
64
|
+
if source is None:
|
|
65
|
+
source = ROOT / 'assets' if is_git_dir() else 'https://ultralytics.com/images/bus.jpg'
|
|
66
|
+
LOGGER.warning(f"WARNING ⚠️ 'source' is missing. Using 'source={source}'.")
|
|
63
67
|
overrides = dict(conf=0.25, task='detect', mode='predict')
|
|
64
68
|
overrides.update(kwargs) # prefer kwargs
|
|
65
69
|
if not self.predictor:
|
|
@@ -84,6 +88,10 @@ class RTDETR:
|
|
|
84
88
|
self.metrics = validator.metrics
|
|
85
89
|
return validator.metrics
|
|
86
90
|
|
|
91
|
+
def info(self, verbose=True):
|
|
92
|
+
"""Get model info"""
|
|
93
|
+
return model_info(self.model, verbose=verbose)
|
|
94
|
+
|
|
87
95
|
@smart_inference_mode()
|
|
88
96
|
def export(self, **kwargs):
|
|
89
97
|
"""
|
|
@@ -114,7 +114,11 @@ sam_model_map = {
|
|
|
114
114
|
|
|
115
115
|
def build_sam(ckpt='sam_b.pt'):
|
|
116
116
|
"""Build a SAM model specified by ckpt."""
|
|
117
|
-
model_builder =
|
|
117
|
+
model_builder = None
|
|
118
|
+
for k in sam_model_map.keys():
|
|
119
|
+
if ckpt.endswith(k):
|
|
120
|
+
model_builder = sam_model_map.get(k)
|
|
121
|
+
|
|
118
122
|
if not model_builder:
|
|
119
123
|
raise FileNotFoundError(f'{ckpt} is not a supported sam model. Available models are: \n {sam_model_map.keys()}')
|
|
120
124
|
|
|
@@ -9,7 +9,7 @@ from .predict import Predictor
|
|
|
9
9
|
class SAM:
|
|
10
10
|
|
|
11
11
|
def __init__(self, model='sam_b.pt') -> None:
|
|
12
|
-
if model and not
|
|
12
|
+
if model and not model.endswith('.pt') and not model.endswith('.pth'):
|
|
13
13
|
# Should raise AssertionError instead?
|
|
14
14
|
raise NotImplementedError('Segment anything prediction requires pre-trained checkpoint')
|
|
15
15
|
self.model = build_sam(model)
|
|
@@ -115,30 +115,42 @@ class BaseMixTransform:
|
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
class Mosaic(BaseMixTransform):
|
|
118
|
-
"""Mosaic augmentation.
|
|
119
|
-
Args:
|
|
120
|
-
imgsz (Sequence[int]): Image size after mosaic pipeline of single
|
|
121
|
-
image. The shape order should be (height, width).
|
|
122
|
-
Default to (640, 640).
|
|
123
118
|
"""
|
|
119
|
+
Mosaic augmentation.
|
|
124
120
|
|
|
125
|
-
|
|
121
|
+
This class performs mosaic augmentation by combining multiple (4 or 9) images into a single mosaic image.
|
|
122
|
+
The augmentation is applied to a dataset with a given probability.
|
|
123
|
+
|
|
124
|
+
Attributes:
|
|
125
|
+
dataset: The dataset on which the mosaic augmentation is applied.
|
|
126
|
+
imgsz (int, optional): Image size (height and width) after mosaic pipeline of a single image. Default to 640.
|
|
127
|
+
p (float, optional): Probability of applying the mosaic augmentation. Must be in the range 0-1. Default to 1.0.
|
|
128
|
+
n (int, optional): The grid size, either 4 (for 2x2) or 9 (for 3x3).
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
def __init__(self, dataset, imgsz=640, p=1.0, n=9):
|
|
126
132
|
"""Initializes the object with a dataset, image size, probability, and border."""
|
|
127
|
-
assert 0 <= p <= 1.0, 'The probability should be in range [0, 1]
|
|
133
|
+
assert 0 <= p <= 1.0, f'The probability should be in range [0, 1], but got {p}.'
|
|
134
|
+
assert n in (4, 9), 'grid must be equal to 4 or 9.'
|
|
128
135
|
super().__init__(dataset=dataset, p=p)
|
|
129
136
|
self.dataset = dataset
|
|
130
137
|
self.imgsz = imgsz
|
|
131
|
-
self.border =
|
|
138
|
+
self.border = [-imgsz // 2, -imgsz // 2] if n == 4 else [-imgsz, -imgsz]
|
|
139
|
+
self.n = n
|
|
132
140
|
|
|
133
141
|
def get_indexes(self):
|
|
134
|
-
"""Return a list of
|
|
135
|
-
return [random.randint(0, len(self.dataset) - 1) for _ in range(
|
|
142
|
+
"""Return a list of random indexes from the dataset."""
|
|
143
|
+
return [random.randint(0, len(self.dataset) - 1) for _ in range(self.n - 1)]
|
|
136
144
|
|
|
137
145
|
def _mix_transform(self, labels):
|
|
138
146
|
"""Apply mixup transformation to the input image and labels."""
|
|
147
|
+
assert labels.get('rect_shape', None) is None, 'rect and mosaic are mutually exclusive.'
|
|
148
|
+
assert len(labels.get('mix_labels', [])), 'There are no other images for mosaic augment.'
|
|
149
|
+
return self._mosaic4(labels) if self.n == 4 else self._mosaic9(labels)
|
|
150
|
+
|
|
151
|
+
def _mosaic4(self, labels):
|
|
152
|
+
"""Create a 2x2 image mosaic."""
|
|
139
153
|
mosaic_labels = []
|
|
140
|
-
assert labels.get('rect_shape', None) is None, 'rect and mosaic is exclusive.'
|
|
141
|
-
assert len(labels.get('mix_labels', [])) > 0, 'There are no other images for mosaic augment.'
|
|
142
154
|
s = self.imgsz
|
|
143
155
|
yc, xc = (int(random.uniform(-x, 2 * s + x)) for x in self.border) # mosaic center x, y
|
|
144
156
|
for i in range(4):
|
|
@@ -172,7 +184,54 @@ class Mosaic(BaseMixTransform):
|
|
|
172
184
|
final_labels['img'] = img4
|
|
173
185
|
return final_labels
|
|
174
186
|
|
|
175
|
-
def
|
|
187
|
+
def _mosaic9(self, labels):
|
|
188
|
+
"""Create a 3x3 image mosaic."""
|
|
189
|
+
mosaic_labels = []
|
|
190
|
+
s = self.imgsz
|
|
191
|
+
hp, wp = -1, -1 # height, width previous
|
|
192
|
+
for i in range(9):
|
|
193
|
+
labels_patch = labels if i == 0 else labels['mix_labels'][i - 1]
|
|
194
|
+
# Load image
|
|
195
|
+
img = labels_patch['img']
|
|
196
|
+
h, w = labels_patch.pop('resized_shape')
|
|
197
|
+
|
|
198
|
+
# Place img in img9
|
|
199
|
+
if i == 0: # center
|
|
200
|
+
img9 = np.full((s * 3, s * 3, img.shape[2]), 114, dtype=np.uint8) # base image with 4 tiles
|
|
201
|
+
h0, w0 = h, w
|
|
202
|
+
c = s, s, s + w, s + h # xmin, ymin, xmax, ymax (base) coordinates
|
|
203
|
+
elif i == 1: # top
|
|
204
|
+
c = s, s - h, s + w, s
|
|
205
|
+
elif i == 2: # top right
|
|
206
|
+
c = s + wp, s - h, s + wp + w, s
|
|
207
|
+
elif i == 3: # right
|
|
208
|
+
c = s + w0, s, s + w0 + w, s + h
|
|
209
|
+
elif i == 4: # bottom right
|
|
210
|
+
c = s + w0, s + hp, s + w0 + w, s + hp + h
|
|
211
|
+
elif i == 5: # bottom
|
|
212
|
+
c = s + w0 - w, s + h0, s + w0, s + h0 + h
|
|
213
|
+
elif i == 6: # bottom left
|
|
214
|
+
c = s + w0 - wp - w, s + h0, s + w0 - wp, s + h0 + h
|
|
215
|
+
elif i == 7: # left
|
|
216
|
+
c = s - w, s + h0 - h, s, s + h0
|
|
217
|
+
elif i == 8: # top left
|
|
218
|
+
c = s - w, s + h0 - hp - h, s, s + h0 - hp
|
|
219
|
+
|
|
220
|
+
padw, padh = c[:2]
|
|
221
|
+
x1, y1, x2, y2 = (max(x, 0) for x in c) # allocate coords
|
|
222
|
+
|
|
223
|
+
# Image
|
|
224
|
+
img9[y1:y2, x1:x2] = img[y1 - padh:, x1 - padw:] # img9[ymin:ymax, xmin:xmax]
|
|
225
|
+
hp, wp = h, w # height, width previous for next iteration
|
|
226
|
+
|
|
227
|
+
labels_patch = self._update_labels(labels_patch, padw, padh)
|
|
228
|
+
mosaic_labels.append(labels_patch)
|
|
229
|
+
final_labels = self._cat_labels(mosaic_labels)
|
|
230
|
+
final_labels['img'] = img9
|
|
231
|
+
return final_labels
|
|
232
|
+
|
|
233
|
+
@staticmethod
|
|
234
|
+
def _update_labels(labels, padw, padh):
|
|
176
235
|
"""Update labels."""
|
|
177
236
|
nh, nw = labels['img'].shape[:2]
|
|
178
237
|
labels['instances'].convert_bbox(format='xyxy')
|
|
@@ -195,8 +254,9 @@ class Mosaic(BaseMixTransform):
|
|
|
195
254
|
'resized_shape': (self.imgsz * 2, self.imgsz * 2),
|
|
196
255
|
'cls': np.concatenate(cls, 0),
|
|
197
256
|
'instances': Instances.concatenate(instances, axis=0),
|
|
198
|
-
'mosaic_border': self.border}
|
|
199
|
-
|
|
257
|
+
'mosaic_border': self.border} # final_labels
|
|
258
|
+
clip_size = self.imgsz * (2 if self.n == 4 else 3)
|
|
259
|
+
final_labels['instances'].clip(clip_size, clip_size)
|
|
200
260
|
return final_labels
|
|
201
261
|
|
|
202
262
|
|
|
@@ -695,7 +755,7 @@ class Format:
|
|
|
695
755
|
def v8_transforms(dataset, imgsz, hyp):
|
|
696
756
|
"""Convert images to a size suitable for YOLOv8 training."""
|
|
697
757
|
pre_transform = Compose([
|
|
698
|
-
Mosaic(dataset, imgsz=imgsz, p=hyp.mosaic
|
|
758
|
+
Mosaic(dataset, imgsz=imgsz, p=hyp.mosaic),
|
|
699
759
|
CopyPaste(p=hyp.copy_paste),
|
|
700
760
|
RandomPerspective(
|
|
701
761
|
degrees=hyp.degrees,
|
|
@@ -201,15 +201,16 @@ class YOLO:
|
|
|
201
201
|
self.model.load(weights)
|
|
202
202
|
return self
|
|
203
203
|
|
|
204
|
-
def info(self, verbose=True):
|
|
204
|
+
def info(self, detailed=False, verbose=True):
|
|
205
205
|
"""
|
|
206
206
|
Logs model info.
|
|
207
207
|
|
|
208
208
|
Args:
|
|
209
|
+
detailed (bool): Show detailed information about model.
|
|
209
210
|
verbose (bool): Controls verbosity.
|
|
210
211
|
"""
|
|
211
212
|
self._check_is_pytorch_model()
|
|
212
|
-
self.model.info(verbose=verbose)
|
|
213
|
+
return self.model.info(detailed=detailed, verbose=verbose)
|
|
213
214
|
|
|
214
215
|
def fuse(self):
|
|
215
216
|
"""Fuse PyTorch Conv2d and BatchNorm2d layers."""
|
|
@@ -549,10 +549,15 @@ class BaseTrainer:
|
|
|
549
549
|
resume = self.args.resume
|
|
550
550
|
if resume:
|
|
551
551
|
try:
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
552
|
+
exists = isinstance(resume, (str, Path)) and Path(resume).exists()
|
|
553
|
+
last = Path(check_file(resume) if exists else get_latest_run())
|
|
554
|
+
|
|
555
|
+
# Check that resume data YAML exists, otherwise strip to force re-download of dataset
|
|
556
|
+
ckpt_args = attempt_load_weights(last).args
|
|
557
|
+
if not Path(ckpt_args['data']).exists():
|
|
558
|
+
ckpt_args['data'] = self.args.data
|
|
559
|
+
|
|
560
|
+
self.args = get_cfg(ckpt_args)
|
|
556
561
|
self.args.model, resume = str(last), True # reinstate
|
|
557
562
|
except Exception as e:
|
|
558
563
|
raise FileNotFoundError('Resume checkpoint not found. Please pass a valid checkpoint to resume from, '
|
|
@@ -233,7 +233,7 @@ def check_requirements(requirements=ROOT.parent / 'requirements.txt', exclude=()
|
|
|
233
233
|
n += 1
|
|
234
234
|
|
|
235
235
|
if s and install and AUTOINSTALL: # check environment variable
|
|
236
|
-
LOGGER.info(f"{prefix}
|
|
236
|
+
LOGGER.info(f"{prefix} Ultralytics requirement{'s' * (n > 1)} {s}not found, attempting AutoUpdate...")
|
|
237
237
|
try:
|
|
238
238
|
assert is_online(), 'AutoUpdate skipped (offline)'
|
|
239
239
|
LOGGER.info(subprocess.check_output(f'pip install --no-cache {s} {cmds}', shell=True).decode())
|
|
@@ -34,7 +34,7 @@ class BboxLoss(nn.Module):
|
|
|
34
34
|
|
|
35
35
|
def forward(self, pred_dist, pred_bboxes, anchor_points, target_bboxes, target_scores, target_scores_sum, fg_mask):
|
|
36
36
|
"""IoU loss."""
|
|
37
|
-
weight =
|
|
37
|
+
weight = target_scores.sum(-1)[fg_mask]
|
|
38
38
|
iou = bbox_iou(pred_bboxes[fg_mask], target_bboxes[fg_mask], xywh=False, CIoU=True)
|
|
39
39
|
loss_iou = ((1.0 - iou) * weight).sum() / target_scores_sum
|
|
40
40
|
|
|
@@ -189,6 +189,7 @@ class TaskAlignedAssigner(nn.Module):
|
|
|
189
189
|
for k in range(self.topk):
|
|
190
190
|
# Expand topk_idxs for each value of k and add 1 at the specified positions
|
|
191
191
|
count_tensor.scatter_add_(-1, topk_idxs[:, :, k:k + 1], ones)
|
|
192
|
+
# count_tensor.scatter_add_(-1, topk_idxs, torch.ones_like(topk_idxs, dtype=torch.int8, device=topk_idxs.device))
|
|
192
193
|
# filter invalid bboxes
|
|
193
194
|
count_tensor.masked_fill_(count_tensor > 1, 0)
|
|
194
195
|
|
|
@@ -165,14 +165,15 @@ def model_info(model, detailed=False, verbose=True, imgsz=640):
|
|
|
165
165
|
f"{'layer':>5} {'name':>40} {'gradient':>9} {'parameters':>12} {'shape':>20} {'mu':>10} {'sigma':>10}")
|
|
166
166
|
for i, (name, p) in enumerate(model.named_parameters()):
|
|
167
167
|
name = name.replace('module_list.', '')
|
|
168
|
-
LOGGER.info('%5g %40s %9s %12g %20s %10.3g %10.3g' %
|
|
169
|
-
(i, name, p.requires_grad, p.numel(), list(p.shape), p.mean(), p.std()))
|
|
168
|
+
LOGGER.info('%5g %40s %9s %12g %20s %10.3g %10.3g %10s' %
|
|
169
|
+
(i, name, p.requires_grad, p.numel(), list(p.shape), p.mean(), p.std(), p.dtype))
|
|
170
170
|
|
|
171
171
|
flops = get_flops(model, imgsz)
|
|
172
172
|
fused = ' (fused)' if model.is_fused() else ''
|
|
173
173
|
fs = f', {flops:.1f} GFLOPs' if flops else ''
|
|
174
174
|
m = Path(getattr(model, 'yaml_file', '') or model.yaml.get('yaml_file', '')).stem.replace('yolo', 'YOLO') or 'Model'
|
|
175
175
|
LOGGER.info(f'{m} summary{fused}: {len(list(model.modules()))} layers, {n_p} parameters, {n_g} gradients{fs}')
|
|
176
|
+
return n_p, flops
|
|
176
177
|
|
|
177
178
|
|
|
178
179
|
def get_num_params(model):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ultralytics
|
|
3
|
-
Version: 8.0.
|
|
3
|
+
Version: 8.0.100
|
|
4
4
|
Summary: Ultralytics YOLOv8 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
|
|
5
5
|
Home-page: https://github.com/ultralytics/ultralytics
|
|
6
6
|
Author: Ultralytics
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataloaders/stream_loaders.py
RENAMED
|
File without changes
|
{ultralytics-8.0.98 → ultralytics-8.0.100}/ultralytics/yolo/data/dataloaders/v5augmentations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|