Датасет составлен на основе поисковой выдачи Яндекс.Картинок, Pinterest, Unsplash и нескольких небольших датасетов с Roboflow ([раз](https://universe.roboflow.com/darinas-workspace/cup-kettle), [два](https://universe.roboflow.com/badredslim/electric_kettles_detection), [три](https://universe.roboflow.com/pruebas-de-200/teapot-f8mdf)). Все картинки проверены на сходство при помощи редактора `geeqie`, что помогло избавиться от большинства дубликатов. Кроме того, все картинки обработаны ImageMagick для получения одинакового для всех размера 640*640 пикселей.
%% Cell type:markdown id: tags:
# Автоматическая разметка датасета
%% Cell type:markdown id: tags:
Попробуем разметить датасет при помощи модели `SAM-2`. К сожалению, эта модель не подошла для нашей задачи. Как выяснилось, эта модель умеет только определять границы объектов, никак не связывая их с семантиеским значением. Вот пример детекции чайника по одной точке, относящейся к нему и выбранной вручную.
%% Cell type:code id: tags:
``` python
!python -m pip install sam2
!python -m pip install huggingface_hub
```
%% Cell type:code id: tags:
``` python
import os
HOME = os.getcwd()
TRAIN_DIR = f"{HOME}/dataset/train"
VAL_DIR = f"{HOME}/dataset/val"
```
%% Cell type:code id: tags:
``` python
import torch
from sam2.sam2_image_predictor import SAM2ImagePredictor
/Users/ischknv/Documents/GitHub/miem/aimm/.venv/lib/python3.12/site-packages/torch/amp/autocast_mode.py:266: UserWarning: User provided device_type of 'cuda', but CUDA is not available. Disabling
Изучив `CLIP`, я понял, что он тоже не подходит, так как выполняет обратное действие: определить все объекты на картинке, не уточняя их позиции.
Наконец, я выбрал `GroundingDINO`, который нам подходит: на вход можно указать список промптов и, после обработки изображения, получить список прямоугольников с этим типом объектов. Воспользуемся же ею!
from groundingdino.util.inference import load_model, load_image, predict, annotate
%cd {HOME}
```
%% Output
/Users/ischknv/Documents/GitHub/miem/aimm/.venv/lib/python3.12/site-packages/IPython/core/magics/osm.py:417: UserWarning: This is now an optional IPython functionality, setting dhist requires you to install the `pickleshare` library.
device = "cuda" if torch.cuda.is_available() else "cpu"
```
%% Output
UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/aten/src/ATen/native/TensorShape.cpp:3596.)
final text_encoder_type: bert-base-uncased
%% Cell type:code id: tags:
``` python
images = sorted(m for m in os.listdir(TRAIN_DIR) if m.lower().endswith(('.png', '.jpg', '.jpeg')))
UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.
UserWarning: None of the inputs have requires_grad=True. Gradients will be None
Speed: 1.1ms preprocess, 159.1ms inference, 0.5ms postprocess per image at shape (1, 3, 640, 640)
%% Cell type:markdown id: tags:
# Результаты
Сделан файн-тюн YOLO, который умеет распознавать чайники: газовые, электрические и заварочные. Между собой классы отличаются не всегда (например, на картинке выше должен быть `kettle`, а распознан `teapot`), но это скорее проблема качества датасета (я и сам не всегда могу чётко сказать разницу). Результаты тренировки можно найти в [папке runs](lab-2/runs/detect/train/). Лучшая метрика `mAP50` составила `0.85204`: около 0.7 для kettle и 0.9 для teapot — есть смысл объединить эти классы, чтобы не "путать" модель и повысить точность.
Датасет составлен на основе поисковой выдачи Яндекс.Картинок, Pinterest, Unsplash и нескольких небольших датасетов с Roboflow ([раз](https://universe.roboflow.com/darinas-workspace/cup-kettle), [два](https://universe.roboflow.com/badredslim/electric_kettles_detection), [три](https://universe.roboflow.com/pruebas-de-200/teapot-f8mdf)). Все картинки проверены на сходство при помощи редактора `geeqie`, что помогло избавиться от большинства дубликатов. Кроме того, все картинки обработаны ImageMagick для получения одинакового для всех размера 640*640 пикселей.
%% Cell type:markdown id: tags:
# Автоматическая разметка датасета
%% Cell type:markdown id: tags:
Попробуем разметить датасет при помощи модели `SAM-2`. К сожалению, эта модель не подошла для нашей задачи. Как выяснилось, эта модель умеет только определять границы объектов, никак не связывая их с семантиеским значением. Вот пример детекции чайника по одной точке, относящейся к нему и выбранной вручную.
%% Cell type:code id: tags:
``` python
!python -m pip install sam2
!python -m pip install huggingface_hub
```
%% Cell type:code id: tags:
``` python
import os
HOME = os.getcwd()
TRAIN_DIR = f"{HOME}/dataset/train"
VAL_DIR = f"{HOME}/dataset/val"
```
%% Cell type:code id: tags:
``` python
import torch
from sam2.sam2_image_predictor import SAM2ImagePredictor
/Users/ischknv/Documents/GitHub/miem/aimm/.venv/lib/python3.12/site-packages/torch/amp/autocast_mode.py:266: UserWarning: User provided device_type of 'cuda', but CUDA is not available. Disabling
Изучив `CLIP`, я понял, что он тоже не подходит, так как выполняет обратное действие: определить все объекты на картинке, не уточняя их позиции.
Наконец, я выбрал `GroundingDINO`, который нам подходит: на вход можно указать список промптов и, после обработки изображения, получить список прямоугольников с этим типом объектов. Воспользуемся же ею!
from groundingdino.util.inference import load_model, load_image, predict, annotate
%cd {HOME}
```
%% Output
/Users/ischknv/Documents/GitHub/miem/aimm/.venv/lib/python3.12/site-packages/IPython/core/magics/osm.py:417: UserWarning: This is now an optional IPython functionality, setting dhist requires you to install the `pickleshare` library.
device = "cuda" if torch.cuda.is_available() else "cpu"
```
%% Output
UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/aten/src/ATen/native/TensorShape.cpp:3596.)
final text_encoder_type: bert-base-uncased
%% Cell type:code id: tags:
``` python
images = sorted(m for m in os.listdir(TRAIN_DIR) if m.lower().endswith(('.png', '.jpg', '.jpeg')))
UserWarning: torch.utils.checkpoint: the use_reentrant parameter should be passed explicitly. In version 2.5 we will raise an exception if use_reentrant is not passed. use_reentrant=False is recommended, but if you need to preserve the current default behavior, you can pass use_reentrant=True. Refer to docs for more details on the differences between the two variants.
UserWarning: None of the inputs have requires_grad=True. Gradients will be None
Speed: 1.1ms preprocess, 159.1ms inference, 0.5ms postprocess per image at shape (1, 3, 640, 640)
%% Cell type:markdown id: tags:
# Результаты
Сделан файн-тюн YOLO, который умеет распознавать чайники: газовые, электрические и заварочные. Между собой классы отличаются не всегда (например, на картинке выше должен быть `kettle`, а распознан `teapot`), но это скорее проблема качества датасета (я и сам не всегда могу чётко сказать разницу). Результаты тренировки можно найти в [папке runs](lab-2/runs/detect/train/). Лучшая метрика `mAP50` составила `0.85204`: около 0.7 для kettle и 0.9 для teapot — есть смысл объединить эти классы, чтобы не "путать" модель и повысить точность.