Введение Недавно опубликовано объявление новый YOLOv5, который концептуально обеспечивает гораздо лучшую степень распознавания набора данных COCO, чем предыдущие версии.
Автор решил опробовать новую модель на задаче по распознаванию марок автомобилей.
Данные
Прежде всего, нам нужны данные.Датасет собирался вручную путем фотографирования припаркованных на стоянке автомобилей с видимым значком бренда (для этого мне пришлось выйти из дома в 5 утра, чтобы не напугать удивленных прохожих).
Разметка данных выполнена с помощью инструмента меткаImg .
Всего было отмечено 118 фотографий автомобилей следующих марок: Lada, Kia, Nissan, Volkswagen, Chevrolet, Ford, Mitsubishi, Renault, Hyundai, Opel. Это довольно оптимистичная цель — попытаться обучить нейронную сеть на таком небольшом наборе данных, однако покажет только практика!
Предварительная обработка
Так как labelImg использует формат Pascal VOC и записывает разметку в файлы XML, а YOLOv5 использует файлы TXT со строками следующего формата: «x-center class-number y-center ширина высота», все нормализованные к единице, мы должны преобразовать разметку в этот формат. Размещаем фотографии в директории CAR_BRANDS/ и пишем код конвертации:Мы будем передавать в нейронную сеть фотографии размера (416, 416), поэтому следующая функция поможет нам изменить их размер:from lxml import etree import cv2 from glob import glob import re CAR_BRANDS_PATH = 'CAR_BRANDS/' classes = {'lada': 0, 'kia': 1, 'nissan': 2, 'volkswagen': 3, 'chevrolet': 4, 'ford': 5, 'mitsubishi': 6, 'renault': 7, 'hyundai': 8, 'opel': 9} def extract_txt(img_path, xml_path, txt_path): img = cv2.imread(img_path) W = img.shape[1] H = img.shape[0] tree = etree.parse(xml_path) root = tree.getroot() with open(txt_path, 'w') as f: for child in root: if child.tag == 'object': for object_child in child: coords = [] if object_child.tag == 'name': f.write(str(classes.get(object_child.text))+' ') if object_child.tag == 'bndbox': for bbox_child in object_child: coords.append(int(bbox_child.text)) xmin = coords[0] xmax = coords[2] ymin = coords[1] ymax = coords[3] w = (xmax - xmin) / W h = (ymax - ymin) / H xc = (xmin + (xmax - xmin) / 2) / W yc = (ymin + (ymax - ymin) / 2) / H f.write(str(xc)+' '+str(yc)+' '+str(w)+' '+str(h)+'\n') xmls = sorted(glob(CAR_BRANDS_PATH + '*.
xml')) for xml_path in xmls: img_path = re.findall('[A-Za-z0-9_/]+', xml_path)[0]+'.
jpg' txt_path = re.findall('[A-Za-z0-9_/]+', img_path)[0]+'.
txt' extract_txt(img_path, xml_path, txt_path)
def resize(folder):
files = glob(folder + '*.
jpg')
for file in files:
img = cv2.imread(file)
img = cv2.resize(img, (416, 416))
cv2.imwrite(file, img)
Увеличение
Ресурс использован для аугментации робопоток Однако вы можете использовать любой доступный вам метод аугментации.Фотографии умножены до 4130, типы увеличения - Обрезка, Яркость, Экспозиция, Шум.
Итоговые файлы были разделены на обучающие, валидационные и тестовые в соотношении 7:2:1.
Образование
Давайте загрузим YOLOv5 из репозитория на Github и установим требования: git clone https://github.com/roboflow-ai/yolov5
pip install -U -r yolov5/requirements.txt
Информация о данных будет храниться в файле data.yaml. Давайте создадим этот файл со следующим содержимым:
train: .
/train/images
val: .
/valid/images
nc: 10
names: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
где train — путь к каталогу, содержащему изображения для поезда, valid — изображения проверки, nc — количество классов, имена — имена классов.
Вам также необходимо поместить архитектуру в каталог yolov5/models/.
Возьмем за основу архитектуру yolov5s.yaml и разместим в custom_yolov5s.yaml следующую информацию: # parameters
nc: 10 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# yolov5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 1-P1/2
[-1, 1, Conv, [128, 3, 2]], # 2-P2/4
[-1, 3, Bottleneck, [128]],
[-1, 1, Conv, [256, 3, 2]], # 4-P3/8
[-1, 9, BottleneckCSP, [256]],
[-1, 1, Conv, [512, 3, 2]], # 6-P4/16
[-1, 9, BottleneckCSP, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 8-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 6, BottleneckCSP, [1024]], # 10
]
# yolov5 head
head:
[[-1, 3, BottleneckCSP, [1024, False]], # 11
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1, 0]], # 12 (P5/32-large)
[-2, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 1, Conv, [512, 1, 1]],
[-1, 3, BottleneckCSP, [512, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1, 0]], # 17 (P4/16-medium)
[-2, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 1, Conv, [256, 1, 1]],
[-1, 3, BottleneckCSP, [256, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1, 0]], # 22 (P3/8-small)
[[], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
Теперь вы можете начать учиться.
Перейдем к yolov5/: cd yolov5/
и обучим нашу модель: python train.py --img 416 --batch 4 --epochs 50 --data '.
/data.yaml' --cfg .
/models/custom_yolov5s.yaml --weights '' --name yolov5s_results --nosave --cache
Результаты
Чтобы протестировать модель, введите следующее: python detect.py --weights weights/last_yolov5s_results.pt --img 416 --conf 0.4 --save-txt --source .
/test/images
При желании вы можете увеличить или уменьшить значение параметра conf — это позволит вам выбирать прогнозы с вероятностью большей, чем указано в conf. Результаты сохраняются в каталог yolov5/inference/output/ (как изображения, так и TXT-файлы (при условии указания флага --save-txt).
Из 12 фотографий, выбранных для теста, бренды распознались в 10 случаях, и все распознанные оказались правильными.
Вполне хороший результат для исходной выборки из 118 фотографий.
Примеры вывода нейросети (для идентификации брендов используем записанный ранее словарь):
И, наконец, давайте подробнее рассмотрим процесс обучения.
Во время тренировки YOLOv5 делает что-то похожее на фотографии:
Это так называемая «мозаичная аугментация» — к фотографиям применяются отражения и разрезание фотографий на части.
Вы можете удалить его, войдя в код train.py и изменив флаг augmet на False. Когда его использование может причинить вред? Например, если бы мы поставили задачу идентифицировать номерные знаки, отражение и разрезание отдельных букв и цифр привело бы не к улучшению, а к ухудшению качества распознавания.
Что дальше?
Во-первых, одним из просторов для творчества может стать перебор различных вариантов архитектур YOLOv5 — все они находятся в yolov5/models/.Напомню, мы использовали yolov5s — он считается самым быстрым, но не лучшим по качеству распознавания.
Также классической темой YOLO является игра со значениями якорей.
Итак, давайте следить за новостями о новых архитектурах нейросетей и пробовать их на собственных данных! Надеюсь, эта статья была вам полезна.
Теги: #Машинное обучение #python #машинное обучение #компьютерное зрение #yolov5
-
Внешний Кадровый Резерв - Это...
19 Oct, 24