mirror of
https://github.com/azaion/ai-training.git
synced 2026-04-22 11:36:36 +00:00
fix augmentation - correct bboxes to be within borders+margin
Add classes = 80 as default number in yaml file
This commit is contained in:
@@ -36,13 +36,12 @@ Linux
|
|||||||
```
|
```
|
||||||
|
|
||||||
**3. Fix possible problems**
|
**3. Fix possible problems**
|
||||||
* Windows:
|
|
||||||
* cv2.error: OpenCV(4.10.0) ...\window.cpp:1301: error: (-2:Unspecified error)
|
* cv2.error: OpenCV(4.10.0) ...\window.cpp:1301: error: (-2:Unspecified error)
|
||||||
```
|
```
|
||||||
pip uninstall opencv-python
|
pip uninstall opencv-python
|
||||||
pip install opencv-python
|
pip install opencv-python
|
||||||
```
|
```
|
||||||
* fbgemm.dll error
|
* fbgemm.dll error (Windows specific)
|
||||||
```
|
```
|
||||||
copypaste libomp140.x86_64.dll to C:\Windows\System32
|
copypaste libomp140.x86_64.dll to C:\Windows\System32
|
||||||
```
|
```
|
||||||
|
|||||||
+11
-11
@@ -1,62 +1,62 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": 0,
|
"Id": 0,
|
||||||
"Name": "Броньована техніка",
|
"Name": "Armored-Vehicle",
|
||||||
"Color": "#80FF0000",
|
"Color": "#80FF0000",
|
||||||
"ColorBrush": "#80FF0000"
|
"ColorBrush": "#80FF0000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 1,
|
"Id": 1,
|
||||||
"Name": "Вантажівка",
|
"Name": "Truck",
|
||||||
"Color": "#8000FF00",
|
"Color": "#8000FF00",
|
||||||
"ColorBrush": "#8000FF00"
|
"ColorBrush": "#8000FF00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 2,
|
"Id": 2,
|
||||||
"Name": "Машина легкова",
|
"Name": "Vehicle",
|
||||||
"Color": "#800000FF",
|
"Color": "#800000FF",
|
||||||
"ColorBrush": "#800000FF"
|
"ColorBrush": "#800000FF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 3,
|
"Id": 3,
|
||||||
"Name": "Артилерія",
|
"Name": "Artillery",
|
||||||
"Color": "#80FFFF00",
|
"Color": "#80FFFF00",
|
||||||
"ColorBrush": "#80FFFF00"
|
"ColorBrush": "#80FFFF00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 4,
|
"Id": 4,
|
||||||
"Name": "Тінь від техніки",
|
"Name": "Shadow",
|
||||||
"Color": "#80FF00FF",
|
"Color": "#80FF00FF",
|
||||||
"ColorBrush": "#80FF00FF"
|
"ColorBrush": "#80FF00FF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 5,
|
"Id": 5,
|
||||||
"Name": "Окопи",
|
"Name": "Trenches",
|
||||||
"Color": "#8000FFFF",
|
"Color": "#8000FFFF",
|
||||||
"ColorBrush": "#8000FFFF"
|
"ColorBrush": "#8000FFFF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 6,
|
"Id": 6,
|
||||||
"Name": "Військовий",
|
"Name": "Military-men",
|
||||||
"Color": "#80000000",
|
"Color": "#80000000",
|
||||||
"ColorBrush": "#80000000"
|
"ColorBrush": "#80000000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 7,
|
"Id": 7,
|
||||||
"Name": "Накати",
|
"Name": "Tyre-tracks",
|
||||||
"Color": "#80800000",
|
"Color": "#80800000",
|
||||||
"ColorBrush": "#80800000"
|
"ColorBrush": "#80800000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 8,
|
"Id": 8,
|
||||||
"Name": "Танк з додатковим захистом",
|
"Name": "Additional-armored-tank",
|
||||||
"Color": "#80008000",
|
"Color": "#80008000",
|
||||||
"ColorBrush": "#80008000"
|
"ColorBrush": "#80008000"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 9,
|
"Id": 9,
|
||||||
"Name": "Дим",
|
"Name": "Smoke",
|
||||||
"Color": "#80000080",
|
"Color": "#80000080",
|
||||||
"ColorBrush": "#80000080"
|
"ColorBrush": "#80000080"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import xml.etree.cElementTree as et
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
labels_dir = 'labels'
|
|
||||||
images_dir = 'images'
|
|
||||||
|
|
||||||
tag_size = 'size'
|
tag_size = 'size'
|
||||||
tag_object = 'object'
|
tag_object = 'object'
|
||||||
@@ -17,9 +15,11 @@ default_class = 1
|
|||||||
image_extensions = ['jpg', 'png', 'jpeg']
|
image_extensions = ['jpg', 'png', 'jpeg']
|
||||||
|
|
||||||
|
|
||||||
def convert(folder, read_annotations, ann_format):
|
def convert(folder, dest_folder, read_annotations, ann_format):
|
||||||
os.makedirs(images_dir, exist_ok=True)
|
dest_images_dir = os.path.join(dest_folder, 'images')
|
||||||
os.makedirs(labels_dir, exist_ok=True)
|
dest_labels_dir = os.path.join(dest_folder, 'labels')
|
||||||
|
os.makedirs(dest_images_dir, exist_ok=True)
|
||||||
|
os.makedirs(dest_labels_dir, exist_ok=True)
|
||||||
|
|
||||||
for f in os.listdir(folder):
|
for f in os.listdir(folder):
|
||||||
if not f[-3:] in image_extensions:
|
if not f[-3:] in image_extensions:
|
||||||
@@ -39,8 +39,8 @@ def convert(folder, read_annotations, ann_format):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'Error conversion for {f}. Error: {e}')
|
print(f'Error conversion for {f}. Error: {e}')
|
||||||
|
|
||||||
shutil.copy(os.path.join(folder, f), os.path.join(images_dir, f))
|
shutil.copy(os.path.join(folder, f), os.path.join(dest_images_dir, f))
|
||||||
with open(os.path.join(labels_dir, f'{Path(label).stem}.txt'), 'w') as new_label_file:
|
with open(os.path.join(dest_labels_dir, f'{Path(label).stem}.txt'), 'w') as new_label_file:
|
||||||
new_label_file.writelines(lines)
|
new_label_file.writelines(lines)
|
||||||
new_label_file.close()
|
new_label_file.close()
|
||||||
print(f'Image {f} has been processed successfully')
|
print(f'Image {f} has been processed successfully')
|
||||||
@@ -115,5 +115,5 @@ def rename_images(folder):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
convert('datasets/others/UAVHeightImages', read_bbox_oriented, 'txt')
|
convert('/azaion/datasets/others/cars_height', '/azaion/datasets/converted', read_bbox_oriented, 'txt')
|
||||||
convert('datasets/others/UAVimages', read_pascal_voc, 'xml')
|
convert('/azaion/datasets/others/cars', '/azaion/datasets/converted', read_pascal_voc, 'xml')
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# prerequisites
|
||||||
|
sudo apt install python3.12-venv python-is-python3
|
||||||
|
if [ ! -f azaion.pt ]; then
|
||||||
|
echo "----ERROR!----"
|
||||||
|
echo "Script requires azaion.pt file model in this folder!!!"
|
||||||
|
echo "----ERROR!----"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# convert PT to ONNX
|
||||||
|
git clone https://github.com/airockchip/ultralytics_yolov8
|
||||||
|
cd ultralytics_yolov8
|
||||||
|
python -m venv env
|
||||||
|
source env/bin/activate
|
||||||
|
pip install .
|
||||||
|
|
||||||
|
cp ../azaion.pt .
|
||||||
|
sed -i -E "s/(model:).*$/\1 azaion.pt/" ultralytics/cfg/default.yaml
|
||||||
|
export PYTHONPATH=./
|
||||||
|
python ./ultralytics/engine/exporter.py
|
||||||
|
cp azaion.onnx ../
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
# convert ONNX to RKNN
|
||||||
|
wget -c https://mirrors.bfsu.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh
|
||||||
|
chmod +x Miniconda3-latest-Linux-x86_64.sh
|
||||||
|
bash Miniconda3-latest-Linux-x86_64.sh
|
||||||
|
source ~/miniconda3/bin/activate
|
||||||
|
conda create -n toolkit2 python=3.11
|
||||||
|
conda activate toolkit2
|
||||||
|
git clone https://github.com/rockchip-linux/rknn-toolkit2.git
|
||||||
|
cd rknn-toolkit2/rknn-toolkit2/packages
|
||||||
|
pip install -r requirements_cp311-1.6.0.txt
|
||||||
|
pip install rknn_toolkit2-1.6.0+81f21f4d-cp311-cp311-linux_x86_64.whl
|
||||||
|
cd ~/opi5-rknn
|
||||||
|
git clone https://github.com/airockchip/rknn_model_zoo.git
|
||||||
|
cd rknn_model_zoo/examples/yolov8/python
|
||||||
|
python convert.py ~/azaion/models/azaion-2024-08-13.onnx rk3588 i8
|
||||||
|
cp ../model/yolov8.rknn ~/azaion/models/azaion-2024-08-13.rknn # Output file form convert script is hard-coded...
|
||||||
+32
-5
@@ -11,10 +11,35 @@ from constants import (data_images_dir, data_labels_dir, processed_images_dir, p
|
|||||||
from dto.imageLabel import ImageLabel
|
from dto.imageLabel import ImageLabel
|
||||||
|
|
||||||
|
|
||||||
|
def correct_bboxes(labels):
|
||||||
|
margin = 0.0005
|
||||||
|
min_size = 0.01
|
||||||
|
res = []
|
||||||
|
for bboxes in labels:
|
||||||
|
x = bboxes[0]
|
||||||
|
y = bboxes[1]
|
||||||
|
half_width = 0.5*bboxes[2]
|
||||||
|
half_height = 0.5*bboxes[3]
|
||||||
|
|
||||||
|
# calc how much bboxes are outside borders ( +small margin ).
|
||||||
|
# value should be negative. If it's positive, then put 0, as no correction
|
||||||
|
w_diff = min( (1 - margin) - (x + half_width), (x - half_width) - margin, 0 )
|
||||||
|
w = bboxes[2] + 2*w_diff
|
||||||
|
if w < min_size:
|
||||||
|
continue
|
||||||
|
h_diff = min( (1 - margin) - (y + half_height), ((y - half_height) - margin), 0)
|
||||||
|
h = bboxes[3] + 2 * h_diff
|
||||||
|
if h < min_size:
|
||||||
|
continue
|
||||||
|
res.append([x, y, w, h, bboxes[4]])
|
||||||
|
return res
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def image_processing(img_ann: ImageLabel) -> [ImageLabel]:
|
def image_processing(img_ann: ImageLabel) -> [ImageLabel]:
|
||||||
transforms = [
|
transforms = [
|
||||||
A.Compose([A.HorizontalFlip(always_apply=True)],
|
A.Compose([A.HorizontalFlip(always_apply=True)],
|
||||||
bbox_params=A.BboxParams(format='yolo')),
|
bbox_params=A.BboxParams(format='yolo', )),
|
||||||
A.Compose([A.RandomBrightnessContrast(always_apply=True)],
|
A.Compose([A.RandomBrightnessContrast(always_apply=True)],
|
||||||
bbox_params=A.BboxParams(format='yolo')),
|
bbox_params=A.BboxParams(format='yolo')),
|
||||||
A.Compose([A.SafeRotate(limit=90, always_apply=True)],
|
A.Compose([A.SafeRotate(limit=90, always_apply=True)],
|
||||||
@@ -33,9 +58,12 @@ def image_processing(img_ann: ImageLabel) -> [ImageLabel]:
|
|||||||
]
|
]
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
labels = correct_bboxes(img_ann.labels)
|
||||||
|
if len(labels) == 0 and len(img_ann.labels) != 0:
|
||||||
|
print('no labels but was!!!')
|
||||||
for i, transform in enumerate(transforms):
|
for i, transform in enumerate(transforms):
|
||||||
try:
|
try:
|
||||||
res = transform(image=img_ann.image, bboxes=img_ann.labels)
|
res = transform(image=img_ann.image, bboxes=labels)
|
||||||
path = Path(img_ann.image_path)
|
path = Path(img_ann.image_path)
|
||||||
name = f'{path.stem}_{i + 1}'
|
name = f'{path.stem}_{i + 1}'
|
||||||
img = ImageLabel(
|
img = ImageLabel(
|
||||||
@@ -51,9 +79,6 @@ def image_processing(img_ann: ImageLabel) -> [ImageLabel]:
|
|||||||
|
|
||||||
|
|
||||||
def write_result(img_ann: ImageLabel):
|
def write_result(img_ann: ImageLabel):
|
||||||
os.makedirs(os.path.dirname(img_ann.image_path), exist_ok=True)
|
|
||||||
os.makedirs(os.path.dirname(img_ann.labels_path), exist_ok=True)
|
|
||||||
|
|
||||||
cv2.imencode('.jpg', img_ann.image)[1].tofile(img_ann.image_path)
|
cv2.imencode('.jpg', img_ann.image)[1].tofile(img_ann.image_path)
|
||||||
print(f'{img_ann.image_path} written')
|
print(f'{img_ann.image_path} written')
|
||||||
|
|
||||||
@@ -92,6 +117,8 @@ def process_image(img_ann):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
os.makedirs(processed_images_dir, exist_ok=True)
|
||||||
|
os.makedirs(processed_labels_dir, exist_ok=True)
|
||||||
while True:
|
while True:
|
||||||
processed_images = set(f.name for f in os.scandir(processed_images_dir))
|
processed_images = set(f.name for f in os.scandir(processed_images_dir))
|
||||||
images = []
|
images = []
|
||||||
|
|||||||
+27
-7
@@ -3,18 +3,38 @@ apt update
|
|||||||
apt upgrade
|
apt upgrade
|
||||||
apt install -y ssh
|
apt install -y ssh
|
||||||
|
|
||||||
|
addgroup sftp
|
||||||
adduser azaionsftp
|
adduser azaionsftp
|
||||||
|
usermod -G sftp azaionsftp
|
||||||
|
usermod -a -G sftp zxsanny
|
||||||
|
|
||||||
mkdir /azaion-media/sftphome
|
chown root:root /home/azaionsftp
|
||||||
chown -R azaionsftp:azaionsftp /azaion-media/sftphome/
|
|
||||||
chmod -R 755 /azaion-media/sftphome/
|
cd /home/azaionsftp
|
||||||
|
mkdir datasets
|
||||||
|
chown -R azaionsftp:azaionsftp datasets
|
||||||
|
mount -o bind /azaion/datasets datasets
|
||||||
|
|
||||||
|
chown -R zxsanny:sftp /azaion/data
|
||||||
|
mkdir data
|
||||||
|
chown -R azaionsftp:azaionsftp data
|
||||||
|
mount -o bind /azaion/data data
|
||||||
|
|
||||||
|
chown -R zxsanny:sftp /azaion/data-processed
|
||||||
|
mkdir data-processed
|
||||||
|
chown -R azaionsftp:azaionsftp data-processed
|
||||||
|
mount -o bind /azaion/data-processed data-processed
|
||||||
|
|
||||||
|
|
||||||
|
chmod -R 755 /home/azaionsftp/
|
||||||
|
|
||||||
cat <<EOT >> /etc/ssh/sshd_config
|
cat <<EOT >> /etc/ssh/sshd_config
|
||||||
Match Group azaionsftp
|
Match Group sftp
|
||||||
ChrootDirectory %h
|
ChrootDirectory %h
|
||||||
|
PasswordAuthentication yes
|
||||||
|
AllowTcpForwarding no
|
||||||
X11Forwarding no
|
X11Forwarding no
|
||||||
ForceCommand internal-sftp
|
ForceCommand internal-sftp
|
||||||
AllowTcpForwarding no
|
|
||||||
PasswordAuthentication yes
|
|
||||||
EOT
|
EOT
|
||||||
service ssh restart
|
service ssh restart
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ train_set = 70
|
|||||||
valid_set = 20
|
valid_set = 20
|
||||||
test_set = 10
|
test_set = 10
|
||||||
|
|
||||||
|
DEFAULT_CLASS_NUM = 80
|
||||||
|
|
||||||
|
|
||||||
def form_dataset(from_date: datetime):
|
def form_dataset(from_date: datetime):
|
||||||
makedirs(today_dataset, exist_ok=True)
|
makedirs(today_dataset, exist_ok=True)
|
||||||
@@ -89,7 +91,10 @@ def create_yaml():
|
|||||||
lines = ['names:']
|
lines = ['names:']
|
||||||
for c in annotation_classes:
|
for c in annotation_classes:
|
||||||
lines.append(f'- {annotation_classes[c].name}')
|
lines.append(f'- {annotation_classes[c].name}')
|
||||||
lines.append(f'nc: {len(annotation_classes)}')
|
classes_count = len(annotation_classes)
|
||||||
|
for c in range(DEFAULT_CLASS_NUM - classes_count):
|
||||||
|
lines.append(f'- Class-{c + classes_count + 1}')
|
||||||
|
lines.append(f'nc: {DEFAULT_CLASS_NUM}')
|
||||||
|
|
||||||
lines.append(f'test: test/images')
|
lines.append(f'test: test/images')
|
||||||
lines.append(f'train: train/images')
|
lines.append(f'train: train/images')
|
||||||
@@ -132,17 +137,19 @@ def get_latest_model():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
latest_date, latest_model = get_latest_model()
|
latest_date, latest_model = get_latest_model()
|
||||||
|
# create_yaml()
|
||||||
# form_dataset(latest_date)
|
# form_dataset(latest_date)
|
||||||
|
|
||||||
|
|
||||||
model_name = latest_model if latest_model is not None and path.isfile(latest_model) else 'yolov8m.yaml'
|
model_name = latest_model if latest_model is not None and path.isfile(latest_model) else 'yolov8m.yaml'
|
||||||
print(f'Initial model: {model_name}')
|
print(f'Initial model: {model_name}')
|
||||||
model = YOLO(model_name)
|
model = YOLO(model_name)
|
||||||
|
|
||||||
# cur_folder = path.join(datasets_dir, f'{prefix}2024-06-18')
|
cur_folder = path.join(datasets_dir, f'{prefix}2024-09-19')
|
||||||
|
|
||||||
cur_folder = today_dataset
|
# cur_folder = today_dataset
|
||||||
yaml = abspath(path.join(cur_folder, 'data.yaml'))
|
yaml = abspath(path.join(cur_folder, 'data.yaml'))
|
||||||
results = model.train(data=yaml, epochs=100, batch=60, imgsz=640)
|
results = model.train(data=yaml, epochs=100, batch=58, imgsz=640)
|
||||||
|
|
||||||
shutil.copytree(results.save_dir, path.join(models_dir, today_folder))
|
shutil.copytree(results.save_dir, path.join(models_dir, today_folder))
|
||||||
shutil.rmtree('runs')
|
shutil.rmtree('runs')
|
||||||
|
|||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||||
|
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
nc: 80 # number of classes
|
||||||
|
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
|
||||||
|
# [depth, width, max_channels]
|
||||||
|
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
|
||||||
|
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
|
||||||
|
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
|
||||||
|
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
|
||||||
|
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
|
||||||
|
|
||||||
|
# YOLOv8.0n backbone
|
||||||
|
backbone:
|
||||||
|
# [from, repeats, module, args]
|
||||||
|
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
|
||||||
|
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
|
||||||
|
- [-1, 3, C2f, [128, True]]
|
||||||
|
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
|
||||||
|
- [-1, 6, C2f, [256, True]]
|
||||||
|
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
|
||||||
|
- [-1, 6, C2f, [512, True]]
|
||||||
|
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
|
||||||
|
- [-1, 3, C2f, [1024, True]]
|
||||||
|
- [-1, 1, SPPF, [1024, 5]] # 9
|
||||||
|
|
||||||
|
# YOLOv8.0n head
|
||||||
|
head:
|
||||||
|
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
|
||||||
|
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
|
||||||
|
- [-1, 3, C2f, [512]] # 12
|
||||||
|
|
||||||
|
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
|
||||||
|
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
|
||||||
|
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
|
||||||
|
|
||||||
|
- [-1, 1, Conv, [256, 3, 2]]
|
||||||
|
- [[-1, 12], 1, Concat, [1]] # cat head P4
|
||||||
|
- [-1, 3, C2f, [512]] # 18 (P4/16-medium)
|
||||||
|
|
||||||
|
- [-1, 1, Conv, [512, 3, 2]]
|
||||||
|
- [[-1, 9], 1, Concat, [1]] # cat head P5
|
||||||
|
- [-1, 3, C2f, [1024]] # 21 (P5/32-large)
|
||||||
|
|
||||||
|
- [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Ultralytics YOLO 🚀, GPL-3.0 license
|
|
||||||
|
|
||||||
# Parameters
|
|
||||||
nc: 50 # number of classes
|
|
||||||
depth_multiple: 0.67 # scales module repeats
|
|
||||||
width_multiple: 0.75 # scales convolution channels
|
|
||||||
|
|
||||||
# YOLOv8.0m backbone
|
|
||||||
backbone:
|
|
||||||
# [from, repeats, module, args]
|
|
||||||
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
|
|
||||||
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
|
|
||||||
- [-1, 3, C2f, [128, True]]
|
|
||||||
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
|
|
||||||
- [-1, 6, C2f, [256, True]]
|
|
||||||
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
|
|
||||||
- [-1, 6, C2f, [512, True]]
|
|
||||||
- [-1, 1, Conv, [768, 3, 2]] # 7-P5/32
|
|
||||||
- [-1, 3, C2f, [768, True]]
|
|
||||||
- [-1, 1, SPPF, [768, 5]] # 9
|
|
||||||
|
|
||||||
# YOLOv8.0m head
|
|
||||||
head:
|
|
||||||
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
|
|
||||||
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
|
|
||||||
- [-1, 3, C2f, [512]] # 13
|
|
||||||
|
|
||||||
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
|
|
||||||
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
|
|
||||||
- [-1, 3, C2f, [256]] # 17 (P3/8-small)
|
|
||||||
|
|
||||||
- [-1, 1, Conv, [256, 3, 2]]
|
|
||||||
- [[-1, 12], 1, Concat, [1]] # cat head P4
|
|
||||||
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
|
|
||||||
|
|
||||||
- [-1, 1, Conv, [512, 3, 2]]
|
|
||||||
- [[-1, 9], 1, Concat, [1]] # cat head P5
|
|
||||||
- [-1, 3, C2f, [768]] # 23 (P5/32-large)
|
|
||||||
|
|
||||||
- [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)
|
|
||||||
Reference in New Issue
Block a user