fotonet 0.1.0a0__py3-none-any.whl
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.
- fotonet/__init__.py +32 -0
- fotonet/_torch_notice.py +21 -0
- fotonet/cli/__init__.py +0 -0
- fotonet/cli/main.py +145 -0
- fotonet/config/models/fotonetl-p2.yaml +29 -0
- fotonet/config/models/fotonetl.yaml +32 -0
- fotonet/config/models/fotonetm-p2.yaml +29 -0
- fotonet/config/models/fotonetm.yaml +32 -0
- fotonet/config/models/fotonetn-p2.yaml +30 -0
- fotonet/config/models/fotonetn.yaml +30 -0
- fotonet/config/models/fotonets-p2.yaml +29 -0
- fotonet/config/models/fotonets.yaml +32 -0
- fotonet/config/models/fotonetx-p2.yaml +29 -0
- fotonet/config/models/fotonetx.yaml +32 -0
- fotonet/config/recipes/fotonetn_scratch.yaml +129 -0
- fotonet/data/__init__.py +0 -0
- fotonet/data/augmentations/__init__.py +40 -0
- fotonet/data/augmentations/boxes.py +126 -0
- fotonet/data/augmentations/compose.py +114 -0
- fotonet/data/augmentations/geometric.py +103 -0
- fotonet/data/augmentations/hyp.py +55 -0
- fotonet/data/augmentations/image.py +97 -0
- fotonet/data/dataset.py +521 -0
- fotonet/engine/__init__.py +0 -0
- fotonet/engine/model.py +1038 -0
- fotonet/engine/results.py +600 -0
- fotonet/engine/runtime.py +121 -0
- fotonet/engine/trainer.py +1486 -0
- fotonet/export/__init__.py +3 -0
- fotonet/export/backends.py +249 -0
- fotonet/metrics/__init__.py +3 -0
- fotonet/metrics/map.py +244 -0
- fotonet/models/__init__.py +0 -0
- fotonet/models/backbone.py +239 -0
- fotonet/models/fotonet.py +112 -0
- fotonet/models/head.py +264 -0
- fotonet/models/neck.py +187 -0
- fotonet/models/scales.py +98 -0
- fotonet/utils/__init__.py +0 -0
- fotonet/utils/boxes.py +79 -0
- fotonet/utils/config.py +101 -0
- fotonet/utils/general.py +13 -0
- fotonet/utils/loss.py +659 -0
- fotonet/utils/matcher.py +296 -0
- fotonet/utils/nms.py +62 -0
- fotonet-0.1.0a0.dist-info/METADATA +165 -0
- fotonet-0.1.0a0.dist-info/RECORD +50 -0
- fotonet-0.1.0a0.dist-info/WHEEL +5 -0
- fotonet-0.1.0a0.dist-info/entry_points.txt +2 -0
- fotonet-0.1.0a0.dist-info/top_level.txt +1 -0
fotonet/__init__.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""FOTO-NET: fast Apache-friendly object detection with an Ultralytics-like API."""
|
|
2
|
+
|
|
3
|
+
from fotonet._torch_notice import maybe_print_torch_notice
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
__version__ = "0.1.0a0"
|
|
7
|
+
__all__ = ["FOTONET", "Vector2", "AnchorPoint", "FocusRegion", "BoxTransform", "__version__"]
|
|
8
|
+
|
|
9
|
+
_PUBLIC_API = {"FOTONET", "Vector2", "AnchorPoint", "FocusRegion", "BoxTransform"}
|
|
10
|
+
|
|
11
|
+
maybe_print_torch_notice()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _load_public_api():
|
|
15
|
+
from fotonet.engine.model import FOTONET
|
|
16
|
+
from fotonet.engine.results import AnchorPoint, BoxTransform, FocusRegion, Vector2
|
|
17
|
+
|
|
18
|
+
public = {
|
|
19
|
+
"FOTONET": FOTONET,
|
|
20
|
+
"Vector2": Vector2,
|
|
21
|
+
"AnchorPoint": AnchorPoint,
|
|
22
|
+
"FocusRegion": FocusRegion,
|
|
23
|
+
"BoxTransform": BoxTransform,
|
|
24
|
+
}
|
|
25
|
+
globals().update(public)
|
|
26
|
+
return public
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def __getattr__(name):
|
|
30
|
+
if name in _PUBLIC_API:
|
|
31
|
+
return _load_public_api()[name]
|
|
32
|
+
raise AttributeError(f"module 'fotonet' has no attribute {name!r}")
|
fotonet/_torch_notice.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Helpers for guiding users to install PyTorch outside package dependencies."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib.util
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
TORCH_INSTALL_MESSAGE = "please download torch for your system at https://pytorch.org"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def is_torch_available():
|
|
13
|
+
return importlib.util.find_spec("torch") is not None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def maybe_print_torch_notice(torch_available=None):
|
|
17
|
+
if torch_available is None:
|
|
18
|
+
torch_available = is_torch_available()
|
|
19
|
+
if not torch_available:
|
|
20
|
+
print(TORCH_INSTALL_MESSAGE, file=sys.stderr)
|
|
21
|
+
|
fotonet/cli/__init__.py
ADDED
|
File without changes
|
fotonet/cli/main.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""FOTO-NET command line interface.
|
|
2
|
+
|
|
3
|
+
Examples:
|
|
4
|
+
fotonet train model=fotonetn data=datasets/coco/coco.yaml epochs=250 batch=16 imgsz=640
|
|
5
|
+
fotonet predict model=fotonet-n source=image.jpg conf=0.25 save=true
|
|
6
|
+
fotonet val model=fotonet-n data=datasets/coco/coco.yaml imgsz=640
|
|
7
|
+
fotonet export model=fotonet-n format=onnx path=dev-tools/runs/fotonet.onnx half=true
|
|
8
|
+
|
|
9
|
+
YOLO-style mode form is also accepted:
|
|
10
|
+
fotonet mode=train model=fotonetn data=coco.yaml epochs=100
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import ast
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
TASK_ALIASES = {
|
|
19
|
+
"detect": "predict",
|
|
20
|
+
"infer": "predict",
|
|
21
|
+
"predict": "predict",
|
|
22
|
+
"track": "track",
|
|
23
|
+
"train": "train",
|
|
24
|
+
"val": "val",
|
|
25
|
+
"validate": "val",
|
|
26
|
+
"export": "export",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _coerce(value):
|
|
31
|
+
raw = str(value).strip()
|
|
32
|
+
low = raw.lower()
|
|
33
|
+
if low in {"true", "false"}:
|
|
34
|
+
return low == "true"
|
|
35
|
+
if low in {"none", "null"}:
|
|
36
|
+
return None
|
|
37
|
+
try:
|
|
38
|
+
return ast.literal_eval(raw)
|
|
39
|
+
except (ValueError, SyntaxError):
|
|
40
|
+
return value
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def parse_args(argv):
|
|
44
|
+
args = {}
|
|
45
|
+
task = None
|
|
46
|
+
remaining = list(argv)
|
|
47
|
+
|
|
48
|
+
if remaining and "=" not in remaining[0]:
|
|
49
|
+
task = remaining.pop(0).lower()
|
|
50
|
+
|
|
51
|
+
for token in remaining:
|
|
52
|
+
if "=" not in token:
|
|
53
|
+
raise SystemExit(f"Invalid argument '{token}'. Use key=value.")
|
|
54
|
+
key, value = token.split("=", 1)
|
|
55
|
+
args[key.replace("-", "_")] = _coerce(value)
|
|
56
|
+
|
|
57
|
+
task = args.pop("mode", args.pop("task", task or "predict"))
|
|
58
|
+
task = TASK_ALIASES.get(str(task).lower())
|
|
59
|
+
if task is None:
|
|
60
|
+
valid = ", ".join(sorted(set(TASK_ALIASES.values())))
|
|
61
|
+
raise SystemExit(f"Invalid task. Use one of: {valid}.")
|
|
62
|
+
return task, args
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _pop_bool(args, key, default=False):
|
|
66
|
+
value = args.pop(key, default)
|
|
67
|
+
return bool(value)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _print_help():
|
|
71
|
+
print(__doc__.strip())
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def main(argv=None):
|
|
75
|
+
argv = sys.argv[1:] if argv is None else argv
|
|
76
|
+
if not argv or argv[0] in {"-h", "--help", "help"}:
|
|
77
|
+
_print_help()
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
from fotonet import FOTONET
|
|
81
|
+
|
|
82
|
+
task, args = parse_args(argv)
|
|
83
|
+
model_name = args.pop("model", "fotonetn")
|
|
84
|
+
imgsz = int(args.pop("imgsz", 640))
|
|
85
|
+
|
|
86
|
+
model = FOTONET(model_name)
|
|
87
|
+
|
|
88
|
+
if task == "train":
|
|
89
|
+
data = args.pop("data", None)
|
|
90
|
+
if not data:
|
|
91
|
+
raise SystemExit("Training requires data=path/to/data.yaml.")
|
|
92
|
+
epochs = int(args.pop("epochs", 100))
|
|
93
|
+
save_path = args.pop("save", "fotonet_trained.pt")
|
|
94
|
+
print(f"FOTO-NET train | model={model_name} data={data} epochs={epochs} imgsz={imgsz}")
|
|
95
|
+
model.train(data=data, epochs=epochs, imgsz=imgsz, **args)
|
|
96
|
+
if save_path:
|
|
97
|
+
model.save(str(save_path), inference_only=True, half=True)
|
|
98
|
+
print(f"saved={save_path}")
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
if task in {"predict", "track"}:
|
|
102
|
+
source = args.pop("source", None)
|
|
103
|
+
if not source:
|
|
104
|
+
raise SystemExit(f"{task} requires source=image.jpg|folder.")
|
|
105
|
+
conf = float(args.pop("conf", 0.25))
|
|
106
|
+
save = _pop_bool(args, "save", True)
|
|
107
|
+
show = _pop_bool(args, "show", False)
|
|
108
|
+
use_nms = _pop_bool(args, "use_nms", False)
|
|
109
|
+
results = model.predict(source, imgsz=imgsz, conf=conf, use_nms=use_nms, **args)
|
|
110
|
+
result_list = results if isinstance(results, list) else [results]
|
|
111
|
+
print(
|
|
112
|
+
f"FOTO-NET {task} | model={model_name} source={source} "
|
|
113
|
+
f"images={len(result_list)} nms_free={not use_nms}"
|
|
114
|
+
)
|
|
115
|
+
if save:
|
|
116
|
+
save_dir = "runs"
|
|
117
|
+
os.makedirs(save_dir, exist_ok=True)
|
|
118
|
+
for i, result in enumerate(result_list):
|
|
119
|
+
result.save(os.path.join(save_dir, f"predict_{i}.jpg"))
|
|
120
|
+
print(f"saved_dir={save_dir}")
|
|
121
|
+
if show and not isinstance(results, list):
|
|
122
|
+
results.show()
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
if task == "val":
|
|
126
|
+
data = args.pop("data", None)
|
|
127
|
+
if not data:
|
|
128
|
+
raise SystemExit("Validation requires data=path/to/data.yaml.")
|
|
129
|
+
metrics = model.val(data=data, imgsz=imgsz, **args)
|
|
130
|
+
print("FOTO-NET val")
|
|
131
|
+
for key, value in metrics.items():
|
|
132
|
+
if key.endswith("per_class"):
|
|
133
|
+
continue
|
|
134
|
+
print(f"{key}={value}")
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
if task == "export":
|
|
138
|
+
fmt = str(args.pop("format", "onnx")).lower()
|
|
139
|
+
path = args.pop("path", f"fotonet_export.{fmt}")
|
|
140
|
+
out = model.export(path=path, format=fmt, imgsz=imgsz, **args)
|
|
141
|
+
print(f"exported={out}")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
main()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# FOTO-NET Large P2 - high-capacity O2O target with P2 small-object head
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.50
|
|
4
|
+
width_multiple: 0.55
|
|
5
|
+
p2_head: true
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p5_gate_blocks: 1
|
|
8
|
+
neck_fusion: weighted
|
|
9
|
+
p2_context_blocks: 1
|
|
10
|
+
p3_context_blocks: 1
|
|
11
|
+
quality_head: true
|
|
12
|
+
|
|
13
|
+
backbone:
|
|
14
|
+
- [Conv, [3, 64, 3, 2]]
|
|
15
|
+
- [Conv, [64, 128, 3, 2]]
|
|
16
|
+
- [C2f, [128, 128, 3, True]]
|
|
17
|
+
- [Conv, [128, 256, 3, 2]]
|
|
18
|
+
- [C2f, [256, 256, 6, True]]
|
|
19
|
+
- [Conv, [256, 512, 3, 2]]
|
|
20
|
+
- [C2f, [512, 512, 9, True]]
|
|
21
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
22
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
23
|
+
|
|
24
|
+
neck:
|
|
25
|
+
width_multiple: 1.0
|
|
26
|
+
depth_multiple: 1.0
|
|
27
|
+
|
|
28
|
+
head:
|
|
29
|
+
width_multiple: 1.0
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# FOTO-NET Large - P2-less high-capacity O2O target
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.50
|
|
4
|
+
width_multiple: 0.55
|
|
5
|
+
p2_head: false
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p3_extra_blocks: 3
|
|
8
|
+
p4_extra_blocks: 2
|
|
9
|
+
p5_extra_blocks: 1
|
|
10
|
+
p5_gate_blocks: 1
|
|
11
|
+
neck_fusion: weighted
|
|
12
|
+
p2_context_blocks: 0
|
|
13
|
+
p3_context_blocks: 1
|
|
14
|
+
quality_head: true
|
|
15
|
+
|
|
16
|
+
backbone:
|
|
17
|
+
- [Conv, [3, 64, 3, 2]]
|
|
18
|
+
- [Conv, [64, 128, 3, 2]]
|
|
19
|
+
- [C2f, [128, 128, 3, True]]
|
|
20
|
+
- [Conv, [128, 256, 3, 2]]
|
|
21
|
+
- [C2f, [256, 256, 6, True]]
|
|
22
|
+
- [Conv, [256, 512, 3, 2]]
|
|
23
|
+
- [C2f, [512, 512, 9, True]]
|
|
24
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
25
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
26
|
+
|
|
27
|
+
neck:
|
|
28
|
+
width_multiple: 1.0
|
|
29
|
+
depth_multiple: 1.0
|
|
30
|
+
|
|
31
|
+
head:
|
|
32
|
+
width_multiple: 1.0
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# FOTO-NET Medium P2 - compact mid-size O2O target with P2 small-object head
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.67
|
|
4
|
+
width_multiple: 0.38
|
|
5
|
+
p2_head: true
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p5_gate_blocks: 1
|
|
8
|
+
neck_fusion: weighted
|
|
9
|
+
p2_context_blocks: 1
|
|
10
|
+
p3_context_blocks: 1
|
|
11
|
+
quality_head: true
|
|
12
|
+
|
|
13
|
+
backbone:
|
|
14
|
+
- [Conv, [3, 64, 3, 2]]
|
|
15
|
+
- [Conv, [64, 128, 3, 2]]
|
|
16
|
+
- [C2f, [128, 128, 6, True]]
|
|
17
|
+
- [Conv, [128, 256, 3, 2]]
|
|
18
|
+
- [C2f, [256, 256, 9, True]]
|
|
19
|
+
- [Conv, [256, 512, 3, 2]]
|
|
20
|
+
- [C2f, [512, 512, 9, True]]
|
|
21
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
22
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
23
|
+
|
|
24
|
+
neck:
|
|
25
|
+
width_multiple: 0.75
|
|
26
|
+
depth_multiple: 0.67
|
|
27
|
+
|
|
28
|
+
head:
|
|
29
|
+
width_multiple: 0.75
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# FOTO-NET Medium - P2-less compact mid-size O2O target
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.67
|
|
4
|
+
width_multiple: 0.38
|
|
5
|
+
p2_head: false
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p3_extra_blocks: 2
|
|
8
|
+
p4_extra_blocks: 1
|
|
9
|
+
p5_extra_blocks: 1
|
|
10
|
+
p5_gate_blocks: 1
|
|
11
|
+
neck_fusion: weighted
|
|
12
|
+
p2_context_blocks: 0
|
|
13
|
+
p3_context_blocks: 1
|
|
14
|
+
quality_head: true
|
|
15
|
+
|
|
16
|
+
backbone:
|
|
17
|
+
- [Conv, [3, 64, 3, 2]]
|
|
18
|
+
- [Conv, [64, 128, 3, 2]]
|
|
19
|
+
- [C2f, [128, 128, 6, True]]
|
|
20
|
+
- [Conv, [128, 256, 3, 2]]
|
|
21
|
+
- [C2f, [256, 256, 9, True]]
|
|
22
|
+
- [Conv, [256, 512, 3, 2]]
|
|
23
|
+
- [C2f, [512, 512, 9, True]]
|
|
24
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
25
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
26
|
+
|
|
27
|
+
neck:
|
|
28
|
+
width_multiple: 0.75
|
|
29
|
+
depth_multiple: 0.67
|
|
30
|
+
|
|
31
|
+
head:
|
|
32
|
+
width_multiple: 0.75
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# FOTO-NET Nano - O2O deployment target, P2 small-object head
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.33
|
|
4
|
+
width_multiple: 0.20
|
|
5
|
+
p2_head: true
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p5_extra_blocks: 1
|
|
8
|
+
p5_gate_blocks: 2
|
|
9
|
+
neck_fusion: weighted
|
|
10
|
+
p2_context_blocks: 1
|
|
11
|
+
p3_context_blocks: 1
|
|
12
|
+
quality_head: true
|
|
13
|
+
|
|
14
|
+
backbone:
|
|
15
|
+
- [Conv, [3, 64, 3, 2]]
|
|
16
|
+
- [Conv, [64, 128, 3, 2]]
|
|
17
|
+
- [C2f, [128, 128, 2, True]]
|
|
18
|
+
- [Conv, [128, 256, 3, 2]]
|
|
19
|
+
- [C2f, [256, 256, 4, True]]
|
|
20
|
+
- [Conv, [256, 512, 3, 2]]
|
|
21
|
+
- [C2f, [512, 512, 4, True]]
|
|
22
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
23
|
+
- [C2f, [1024, 1024, 2, True]]
|
|
24
|
+
|
|
25
|
+
neck:
|
|
26
|
+
width_multiple: 0.25
|
|
27
|
+
depth_multiple: 0.33
|
|
28
|
+
|
|
29
|
+
head:
|
|
30
|
+
width_multiple: 0.25
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# FOTO-NET Nano-0 - P2-less edge/general deployment target
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.42
|
|
4
|
+
width_multiple: 0.205
|
|
5
|
+
p2_head: false
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p5_extra_blocks: 1
|
|
8
|
+
p5_gate_blocks: 2
|
|
9
|
+
neck_fusion: weighted
|
|
10
|
+
p2_context_blocks: 0
|
|
11
|
+
p3_context_blocks: 1
|
|
12
|
+
quality_head: false
|
|
13
|
+
|
|
14
|
+
backbone:
|
|
15
|
+
- [Conv, [3, 64, 3, 2]]
|
|
16
|
+
- [Conv, [64, 128, 3, 2]]
|
|
17
|
+
- [C2f, [128, 128, 2, true]]
|
|
18
|
+
- [Conv, [128, 256, 3, 2]]
|
|
19
|
+
- [C2f, [256, 256, 5, true]]
|
|
20
|
+
- [Conv, [256, 512, 3, 2]]
|
|
21
|
+
- [C2f, [512, 512, 5, true]]
|
|
22
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
23
|
+
- [C2f, [1024, 1024, 2, true]]
|
|
24
|
+
|
|
25
|
+
neck:
|
|
26
|
+
width_multiple: 0.205
|
|
27
|
+
depth_multiple: 0.42
|
|
28
|
+
|
|
29
|
+
head:
|
|
30
|
+
width_multiple: 0.205
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# FOTO-NET Small P2 - compact O2O target with P2 small-object head
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.33
|
|
4
|
+
width_multiple: 0.30
|
|
5
|
+
p2_head: true
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p5_gate_blocks: 1
|
|
8
|
+
neck_fusion: weighted
|
|
9
|
+
p2_context_blocks: 1
|
|
10
|
+
p3_context_blocks: 1
|
|
11
|
+
quality_head: true
|
|
12
|
+
|
|
13
|
+
backbone:
|
|
14
|
+
- [Conv, [3, 64, 3, 2]]
|
|
15
|
+
- [Conv, [64, 128, 3, 2]]
|
|
16
|
+
- [C2f, [128, 128, 3, True]]
|
|
17
|
+
- [Conv, [128, 256, 3, 2]]
|
|
18
|
+
- [C2f, [256, 256, 6, True]]
|
|
19
|
+
- [Conv, [256, 512, 3, 2]]
|
|
20
|
+
- [C2f, [512, 512, 6, True]]
|
|
21
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
22
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
23
|
+
|
|
24
|
+
neck:
|
|
25
|
+
width_multiple: 0.50
|
|
26
|
+
depth_multiple: 0.33
|
|
27
|
+
|
|
28
|
+
head:
|
|
29
|
+
width_multiple: 0.50
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# FOTO-NET Small - P2-less compact O2O deployment target
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.33
|
|
4
|
+
width_multiple: 0.30
|
|
5
|
+
p2_head: false
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p3_extra_blocks: 2
|
|
8
|
+
p4_extra_blocks: 1
|
|
9
|
+
p5_extra_blocks: 1
|
|
10
|
+
p5_gate_blocks: 1
|
|
11
|
+
neck_fusion: weighted
|
|
12
|
+
p2_context_blocks: 0
|
|
13
|
+
p3_context_blocks: 1
|
|
14
|
+
quality_head: true
|
|
15
|
+
|
|
16
|
+
backbone:
|
|
17
|
+
- [Conv, [3, 64, 3, 2]]
|
|
18
|
+
- [Conv, [64, 128, 3, 2]]
|
|
19
|
+
- [C2f, [128, 128, 3, True]]
|
|
20
|
+
- [Conv, [128, 256, 3, 2]]
|
|
21
|
+
- [C2f, [256, 256, 6, True]]
|
|
22
|
+
- [Conv, [256, 512, 3, 2]]
|
|
23
|
+
- [C2f, [512, 512, 6, True]]
|
|
24
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
25
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
26
|
+
|
|
27
|
+
neck:
|
|
28
|
+
width_multiple: 0.50
|
|
29
|
+
depth_multiple: 0.33
|
|
30
|
+
|
|
31
|
+
head:
|
|
32
|
+
width_multiple: 0.50
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# FOTO-NET Extra-Large P2 - max-capacity O2O target with P2 small-object head
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.50
|
|
4
|
+
width_multiple: 0.70
|
|
5
|
+
p2_head: true
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p5_gate_blocks: 1
|
|
8
|
+
neck_fusion: weighted
|
|
9
|
+
p2_context_blocks: 1
|
|
10
|
+
p3_context_blocks: 1
|
|
11
|
+
quality_head: true
|
|
12
|
+
|
|
13
|
+
backbone:
|
|
14
|
+
- [Conv, [3, 64, 3, 2]]
|
|
15
|
+
- [Conv, [64, 128, 3, 2]]
|
|
16
|
+
- [C2f, [128, 128, 3, True]]
|
|
17
|
+
- [Conv, [128, 256, 3, 2]]
|
|
18
|
+
- [C2f, [256, 256, 6, True]]
|
|
19
|
+
- [Conv, [256, 512, 3, 2]]
|
|
20
|
+
- [C2f, [512, 512, 9, True]]
|
|
21
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
22
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
23
|
+
|
|
24
|
+
neck:
|
|
25
|
+
width_multiple: 1.25
|
|
26
|
+
depth_multiple: 1.0
|
|
27
|
+
|
|
28
|
+
head:
|
|
29
|
+
width_multiple: 1.25
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# FOTO-NET Extra-Large - P2-less max-capacity O2O target
|
|
2
|
+
nc: 80
|
|
3
|
+
depth_multiple: 0.50
|
|
4
|
+
width_multiple: 0.70
|
|
5
|
+
p2_head: false
|
|
6
|
+
reg_max: 1
|
|
7
|
+
p3_extra_blocks: 3
|
|
8
|
+
p4_extra_blocks: 2
|
|
9
|
+
p5_extra_blocks: 1
|
|
10
|
+
p5_gate_blocks: 1
|
|
11
|
+
neck_fusion: weighted
|
|
12
|
+
p2_context_blocks: 0
|
|
13
|
+
p3_context_blocks: 1
|
|
14
|
+
quality_head: true
|
|
15
|
+
|
|
16
|
+
backbone:
|
|
17
|
+
- [Conv, [3, 64, 3, 2]]
|
|
18
|
+
- [Conv, [64, 128, 3, 2]]
|
|
19
|
+
- [C2f, [128, 128, 3, True]]
|
|
20
|
+
- [Conv, [128, 256, 3, 2]]
|
|
21
|
+
- [C2f, [256, 256, 6, True]]
|
|
22
|
+
- [Conv, [256, 512, 3, 2]]
|
|
23
|
+
- [C2f, [512, 512, 9, True]]
|
|
24
|
+
- [Conv, [512, 1024, 3, 2]]
|
|
25
|
+
- [C2f, [1024, 1024, 3, True]]
|
|
26
|
+
|
|
27
|
+
neck:
|
|
28
|
+
width_multiple: 1.25
|
|
29
|
+
depth_multiple: 1.0
|
|
30
|
+
|
|
31
|
+
head:
|
|
32
|
+
width_multiple: 1.25
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# FOTO-NET-N scratch recipe for COCO-style object detection.
|
|
2
|
+
# Designed for full training, not smoke tests.
|
|
3
|
+
|
|
4
|
+
model: fotonetn
|
|
5
|
+
pretrained: false
|
|
6
|
+
resume: false
|
|
7
|
+
distill_teacher: null
|
|
8
|
+
distill_weight: 0.0
|
|
9
|
+
|
|
10
|
+
train:
|
|
11
|
+
epochs: 500
|
|
12
|
+
imgsz: 640
|
|
13
|
+
imgsz_schedule:
|
|
14
|
+
- [0.35, 640]
|
|
15
|
+
batch: 16
|
|
16
|
+
val_batch: 8
|
|
17
|
+
nbs: 128
|
|
18
|
+
workers: 4
|
|
19
|
+
pin_memory: true
|
|
20
|
+
cache_to_ram: true
|
|
21
|
+
ram_cache_images: 1024
|
|
22
|
+
cache_labels: true
|
|
23
|
+
disk_cache_images: false
|
|
24
|
+
amp: true
|
|
25
|
+
val_amp: true
|
|
26
|
+
cos_lr: true
|
|
27
|
+
compile_model: false
|
|
28
|
+
cuda_graphs: false
|
|
29
|
+
val_period: 5
|
|
30
|
+
val_subset_size: 0
|
|
31
|
+
full_val_after: 0.90
|
|
32
|
+
save_period: -1
|
|
33
|
+
slim_best: true
|
|
34
|
+
best_metric: mAP50_95
|
|
35
|
+
|
|
36
|
+
optimizer:
|
|
37
|
+
# Current trainer implements SGD. Keep MuSGD as future recipe target once optimizer lands.
|
|
38
|
+
name: sgd
|
|
39
|
+
lr0: 0.0054
|
|
40
|
+
lrf: 0.015
|
|
41
|
+
momentum: 0.947
|
|
42
|
+
weight_decay: 0.00064
|
|
43
|
+
warmup_epochs: 3
|
|
44
|
+
|
|
45
|
+
augment:
|
|
46
|
+
mosaic: 0.909
|
|
47
|
+
mixup: 0.012
|
|
48
|
+
copy_paste: 0.075
|
|
49
|
+
copy_paste_mode: flip
|
|
50
|
+
close_mosaic: 15
|
|
51
|
+
scale: 0.562
|
|
52
|
+
fliplr: 0.606
|
|
53
|
+
flipud: 0.0
|
|
54
|
+
degrees: 1.11
|
|
55
|
+
shear: 1.46
|
|
56
|
+
translate: 0.071
|
|
57
|
+
hsv_h: 0.014
|
|
58
|
+
hsv_s: 0.645
|
|
59
|
+
hsv_v: 0.566
|
|
60
|
+
bgr: 0.106
|
|
61
|
+
mixup_alpha: 32.0
|
|
62
|
+
|
|
63
|
+
loss:
|
|
64
|
+
box: 7.5
|
|
65
|
+
cls: 1.0
|
|
66
|
+
dfl: 1.5
|
|
67
|
+
dfl_mean_over_coords: true
|
|
68
|
+
o2o_label_smoothing: 0.01
|
|
69
|
+
o2m_label_smoothing: 0.05
|
|
70
|
+
focal_gamma_pos: 2.0
|
|
71
|
+
focal_gamma_neg: 2.0
|
|
72
|
+
quality_targets: true
|
|
73
|
+
quality_power: 1.0
|
|
74
|
+
quality_floor: 0.05
|
|
75
|
+
quality_start_epoch: 25
|
|
76
|
+
quality_warmup_epochs: 50
|
|
77
|
+
qfl_beta: 2.0
|
|
78
|
+
hard_negative_topk: 256
|
|
79
|
+
hard_negative_weight: 0.10
|
|
80
|
+
hard_negative_min_score: 0.15
|
|
81
|
+
hard_negative_start_epoch: 8
|
|
82
|
+
hard_negative_warmup_epochs: 32
|
|
83
|
+
o2o_weight: 1.0
|
|
84
|
+
o2m_weight: 1.0
|
|
85
|
+
o2m_full_epochs: 250
|
|
86
|
+
o2m_sparse_epochs: 400
|
|
87
|
+
o2m_every_n_steps: 4
|
|
88
|
+
o2m_disable_epoch: 400
|
|
89
|
+
consistency_weight: 0.35
|
|
90
|
+
consistency_start_epoch: 10
|
|
91
|
+
consistency_warmup_epochs: 40
|
|
92
|
+
consistency_cls_weight: 0.25
|
|
93
|
+
consistency_box_weight: 0.75
|
|
94
|
+
prog_loss: true
|
|
95
|
+
prog_start_epoch: 1
|
|
96
|
+
prog_warmup_epochs: 60
|
|
97
|
+
cls_start_factor: 1.50
|
|
98
|
+
box_start_factor: 1.30
|
|
99
|
+
dfl_start_factor: 0.85
|
|
100
|
+
quality: 1.0
|
|
101
|
+
quality_loss_start_epoch: 1
|
|
102
|
+
quality_loss_warmup_epochs: 25
|
|
103
|
+
|
|
104
|
+
matcher:
|
|
105
|
+
topk: 8
|
|
106
|
+
alpha: 1.0
|
|
107
|
+
beta: 2.0
|
|
108
|
+
cost_class: 2.0
|
|
109
|
+
cost_bbox: 2.0
|
|
110
|
+
cost_giou: 1.0
|
|
111
|
+
exact_o2o: true
|
|
112
|
+
exact_o2o_warmup_epochs: 10
|
|
113
|
+
exact_o2o_period: 8
|
|
114
|
+
exact_o2o_period_end_epoch: 250
|
|
115
|
+
min_small_assign: 4
|
|
116
|
+
small_obj_px: 8.0
|
|
117
|
+
|
|
118
|
+
smoke_limits:
|
|
119
|
+
max_epochs_2500_images: 15
|
|
120
|
+
max_epochs_5000_images: 8
|
|
121
|
+
recommended_quick_check:
|
|
122
|
+
epochs: 2
|
|
123
|
+
max_images: 256
|
|
124
|
+
imgsz: 128
|
|
125
|
+
val_subset_size: 64
|
|
126
|
+
full_val_after: 1.01 # keep validation subset on final smoke epoch
|
|
127
|
+
mosaic: 0.0
|
|
128
|
+
mixup: 0.0
|
|
129
|
+
copy_paste: 0.0
|
fotonet/data/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Public augmentation API."""
|
|
2
|
+
from fotonet.data.augmentations.boxes import (
|
|
3
|
+
bbox_ioa,
|
|
4
|
+
clip_boxes_xyxy,
|
|
5
|
+
filter_boxes_xywhn,
|
|
6
|
+
sanitize_boxes_xywhn,
|
|
7
|
+
xywhn_to_xyxy,
|
|
8
|
+
xyxy_to_xywhn,
|
|
9
|
+
)
|
|
10
|
+
from fotonet.data.augmentations.compose import copy_paste, finalize_sample, load_mosaic, mixup
|
|
11
|
+
from fotonet.data.augmentations.geometric import random_affine
|
|
12
|
+
from fotonet.data.augmentations.hyp import DEFAULT_AUGMENT_HYP, build_augment_hyp
|
|
13
|
+
from fotonet.data.augmentations.image import (
|
|
14
|
+
augment_hsv_safe,
|
|
15
|
+
letterbox_resize,
|
|
16
|
+
random_channel_swap,
|
|
17
|
+
random_flip,
|
|
18
|
+
to_tensor,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"DEFAULT_AUGMENT_HYP",
|
|
23
|
+
"augment_hsv_safe",
|
|
24
|
+
"bbox_ioa",
|
|
25
|
+
"build_augment_hyp",
|
|
26
|
+
"clip_boxes_xyxy",
|
|
27
|
+
"copy_paste",
|
|
28
|
+
"filter_boxes_xywhn",
|
|
29
|
+
"finalize_sample",
|
|
30
|
+
"letterbox_resize",
|
|
31
|
+
"load_mosaic",
|
|
32
|
+
"mixup",
|
|
33
|
+
"random_affine",
|
|
34
|
+
"random_channel_swap",
|
|
35
|
+
"random_flip",
|
|
36
|
+
"sanitize_boxes_xywhn",
|
|
37
|
+
"to_tensor",
|
|
38
|
+
"xywhn_to_xyxy",
|
|
39
|
+
"xyxy_to_xywhn",
|
|
40
|
+
]
|