robossembler.org/docs/software/dataset-generator.md

414 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Генерация датасетов
---
Одной из подзадач управления робототехнической системой является задача обнаружения и классификации объектов в сцене, реализуемая с помощью камеры (машинного зрения). Одним из методов решения данной задачи является использование нейросетевой модели, полученной в ходе обучения на предварительно подготовленных наборах данных. Разработанный модуль генерации наборов данных (датасетов) позволяет автоматизировать процесс их подготовки. Полигональные модели экспортируются из CAD-системы - в результате получается mesh-файл формата `obj`. В ходе генерации формируется сцена для симуляции окружения робота (файл сцены в формате blend). В модуле используется пакет создания синтетических изображений BlenderProc, с помощью которого подготавливается набора данных для обучения нейросети.
## Обнаружению объектов в формате COCO
В качестве выходного форма# Модуль восприятия окружения роботом rbs_perception
## Навык обнаружения объектов (Object Detection). Описание API.
Вначале попытаемся описать полную последовательность действий по подготовке и использованию навыка обнаружения объектов. Задача обнаружения объектов сенсорами робота (в частности, RGB камерой в нашем случае) ставится в случае, например, когда необходимо в заданном окружении (сцене) определить наличие или отсутствие необходимых деталей для сборки изделия. Такие детали представлены в информационной среде в виде ассетов, хранимых в базе данных с заданными характеристиками. Поэтому входным параметром навыка обнаружения объектов является список ассетов, экземпляры которых в текущей задаче необходимо обнаруживать. Результатом использования навыка в информационной системе будет являться получение данных о заданном ассете на конкретном изображении, полученном с помощью RGB камеры.
Начальным этапом навыка является создание датасета, состоящего из синтетических изображений, полученных с использованием пакета [BlenderProc](https://github.com/DLR-RM/BlenderProc). Этот датасет представляет из себя набор файлов изображений и файлов меток к ним, а также файл аннотации, описывающий весь датасет в целом. Он имеет определённую структуру папок и будет использован для обучения нейросетевой модели обнаружения объектов на реальных изображениях в работе (runtime-режим). После создания такой датасет должен быть помещён в базу данных, как единый объект, с заданными характеристиками. В дальнейшем датасет может быть пополнен другими изображениями (например, фото из реального окружения робота), позволяющими произвести дообучение нейросети и улучшить качество работы навыка.
На втором этапе происходит обучение нейросетевой модели [YOLOv8](https://github.com/ultralytics/ultralytics). На выходе получаем файл весов модели, который также помещается в базу данных, с указанием версии этого файла и параметров обучения.
Теперь мы имеем всё необходимое для использования навыка обнаружения объектов (Object Detection) в реальном сценарии при управлении роботом в режиме runtime.
Рассмотрим наиболее общий вариант использования этого навыка в среде ROS2.
Первым шагом будет являться первоначальный запуск lifecycle-узла ROS2, отвечающего за работу навыка. Чтобы начать процесс обнаружения конкретной детали на изображении нужно выполнить стартовые действия по шаблону в дереве поведения, задав необходимые параметры процесса (топики получения изображения и выдачи результатов обнаружения, режим работы и другие). После решения поставленной задачи обнаружения конкретного объекта выполняются действия по шаблону приостановки работы навыка. Данные шаблоны деревьев поведения выполняются с помощью исполнителя [BehaviorTree](https://github.com/BehaviorTree/BehaviorTree.ROS2). Затем можно начать обнаружение другого объекта, вновь выполнив стартовый шаблон действий и подготовив новые параметры процесса.
Теперь перейдём к полному описанию данного API.
### Создание датасета
Для создания датасета используется модуль на Python для BlenderProc. Внешними параметрами для модуля являются:
- файл, описывающий параметры рандомизиции, а также объекты сцены с подготовленными мешами (файл *.json)
- выходной каталог.
Формируется сцена для случайного размещения в ней объектов из описания. Затем производится рендеринг полученной сцены с рандомизацией параметров освещения, текстур и размещением камеры. Имена объектов должны совпадать с именами ассетов в нашей базе данных.
В результате будет получен датасет в формате [BOP](../technologies/cv-perception-methods#соревнование-bop-benchmark-of-pose-estimation)
Пример запуска модуля генерации датасета:
```bash
blenderproc run renderBOPdataset2.py --form description.json --path /home/user/path/to/dataset
```
Пример файла description.json:
```json
{"output":{
"datasetObjects":{
"details":[
{"name":"star",
"inertia":{
"ixx":0.1,"ixy":0,"ixz":0,"iyy":0.1,"iyz":0,"izz":0.1
},
"mass":"0",
"visual":"/assets/libs/objects/star.dae",
"collision":"/assets/libs/objects/star.stl",
"type":"env",
"material_path":"",
"part_path":"/libs/objects/star.stl",
"fbx":"/home/webservice/server/build/public/4c4f3909-74b0-4206-aec1-fc4acd3a1081/assets/libs/objects/star.fbx",
"solidType":"active",
"isSelect":true
}
]
},
"typedataset":"ObjectDetection",
"models_randomization":{
"loc_range_low":[-1,-1,0],"loc_range_high":[1,1,2]
},
"scene":{
"objects":[
{"name":"floor","collision_shape":"BOX","loc_xyz":[0,0,0],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}},
{"name":"star","collision_shape":"BOX","loc_xyz":[0,0,0.2],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}
],
"lights":[
{"id":1,"type":"SUN","loc_xyz":[5,5,5],"rot_euler":[-0.06,0.61,-0.19],"color_range_low":[0.5,0.5,0.5],"color_range_high":[1,1,1],"energy_range":[2,9]}
]
},
"camera_position":{
"center_shell":[0,0,0],
"radius_range":[0.3,0.65],
"elevation_range":[10,90]
},
"generation":{
"n_cam_pose":3,
"n_sample_on_pose":3,
"n_series":222,
"image_format":"JPEG",
"image_size_wh":[640,480]
}
}
```
В результате работы модуля в папке '/home/user/path/to/dataset' будет создана файловая структура с датасетом.
### Обучение модели Yolov8.
Для обучения модели используется модуль на Python. Внешним параметром для модуля является:
- каталог с датасетом, сгенерированный на первом этапе.
Пример запуска модуля обучения:
```bash
python train_Yolo.py --path /home/user/path/to/dataset --epoch 11 --outpath /home/user/path/to/weights
```
- path: путь к каталогу с датасетом
- epoch 11: количество эпох обучения (пока рекомендуем 30-50)
В результате работы создается файл весов нейросети с лучшими характеристиками обнаружения best.pt
### Использование навыка в ROS2 для обнаружения объекта на изображении (runtime).
1. Подготовить папку с файлами BT v.4
* Папка /path/to/bt/
* bt.xml
```xml
<root BTCPP_format="4">
<BehaviorTree ID="Main">
<Sequence>
<Action ID="RbsAction" do="ObjectDetection" command="odConfigure" sid="a"></Action>
</Sequence>
</BehaviorTree>
</root>
```
* skills.json
```json
{"skills": [
{
"sid": "a",
"SkillPackage": {
"name": "Robossembler", "version": "1", "format": "1.0"
},
"Module": {
"node_name": "lc_yolo", "name": "ObjectDetection", "description": "Object detection skill with YOLOv8"
},
"BTAction": [
{
"name": "odConfigure",
"type": "run",
"param": [
{
"type": "weights",
"dependency": {"object_name": "board", "weights_file": "/home/shalenikol/0_rbs/w_od_board.pt"}
},
{
"type": "topic",
"dependency": {
"type": "topic",
"topicType": "sensor_msgs/msg/Image",
"sid": "7b832b17-3030-4758-aab5-96a5046797f7",
"topicOut": "/robot_camera/image"
},
"isFilled": true
}
],
"result": [],
"typeAction": "ACTION"
}
],
"topicsOut": [
{
"name": "lc_yolo/object_detection",
"type": "rbs_skill_interfaces/msg/BoundBox"
}
],
"Launch": {
"executable": "od_yolo_lc.py",
"package": "rbss_objectdetection"
}
}
]}
```
2. Запуск интерфейсной ноды с сервером навыка, реализующего алгоритм обнаружения объектов.
```bash
ros2 launch rbs_bt_executor interface.launch.py bt_path:=/path/to/bt
```
3. Запуск процесса обнаружения заданного объекта через дерево поведения.
Выполняется командой:
```bash
ros2 launch rbs_bt_executor rbs_executor.launch.py bt_path:=/path/to/bt
```
После этого узел начинает публиковать в выходной топик информацию об обнаружении объекта на каждом полученном с камеры изображении.
4. Прекращение процесса обнаружения объекта.
Для завершения навыка нужно выполнить дерево поведения:
```xml
<root BTCPP_format="4">
<BehaviorTree ID="Main">
<Sequence>
<Action ID="RbsAction" do="ObjectDetection" command="odStop" sid="b"></Action>
</Sequence>
</BehaviorTree>
</root>
```
Файл skills.json
```json
{"skills": [
{
"sid": "b",
"SkillPackage": { "name": "Robossembler", "version": "1", "format": "1.0" },
"Module": {"node_name": "lc_yolo", "name": "ObjectDetection", "description": "Object detection skill with YOLOv8"},
"BTAction": [
{
"name": "odStop",
"type": "stop",
"param": [],
"result": [],
"typeAction": "ACTION"
}
],
"topicsOut": [
{
"name": "lc_yolo/object_detection",
"type": "rbs_skill_interfaces/msg/BoundBox"
}
],
"Launch": {
"executable": "od_yolo_lc.py",
"package": "rbss_objectdetection"
}
}
]}
```
Команда запуска этого дерева та же, что и в пункте 3.
После выполнения этих действий lifecycle-узел навыка перейдёт в начальное состояние и можно, повторив пункт 1-3, вновь запустить процесс обнаружения уже с другим объектом.
ного модуля являются: модель объекта в формате `obj`, файл описания сцены в формате `blend` и параметры генерации. Интерфейс реализован через параметры командной строки (Command Line Interface — CLI):
- `scene` (путь к файлу описания сцены в формате blend);
- `obj_path`: путь к каталогу с файлами описания детектируемых объектов в формате `obj`;
- `output_dir`: выходной каталог;
- `vhacd_path`: каталог, в котором должен быть установлен или уже установлен vhacd;
- `-imgs`: количество серий рендеринга (по 15 изображений в каждой серии) на выходе
Пример вызова:
```bash
blenderproc run objs2Yolov4dataset.py [scene] [obj_path] [output_dir] [vhacd_path] [imgs 1]
```
Пример полученных синтетических изображений из набора:
![](img/dataset-generation-example-obj-detection-yolo4.jpg)
### Производительность
Процесс создания набора изображений для одной детали в количестве 3000 шт. занимает около 10 часов машинного времени (1 CPU Ryzen 3700X + 1 GPU Nvidia RTX 2060 Super), поэтому для снижения ресурсоёмкости работы алгоритма применяется оригинальный метод - на вход программы подаются вместе со сценой также набор 3D-моделей заданных объектов для их совместного включения в изображения, что соответствует реальным условиям работы, где необходимо обнаруживать и распознавать сразу множество различных объектов, представляющих детали сборки или оснастку. Помимо этого, данный подход позволяет сократить размер общего дискового пространства, занимаемого файлами с весами нейросетевых моделей всех деталей, что также полезно для прикладных применений.
## Обнаружение объектов в формате BOP Challenge
Внешними параметрами для модуля являются:
1. Файл, описывающий параметры рандомизиции, а также объекты сцены с подготовленными мешами (файл *.json)
2. Выходной каталог.
Формируется сцена для случайного размещения в ней объектов из описания. Затем производится рендеринг полученной сцены с рандомизацией параметров освещения, текстур и размещением камеры. Имена объектов должны совпадать с именами ассетов в нашей базе данных.
Пример запуска модуля генерации датасета:
```bash
blenderproc run renderBOPdataset2.py --form description.json --path /home/user/path/to/dataset
```
Пример файла description.json:
```json
{"output":{
"datasetObjects":{
"details":[
{"name":"star",
"inertia":{
"ixx":0.1,"ixy":0,"ixz":0,"iyy":0.1,"iyz":0,"izz":0.1
},
"mass":"0",
"visual":"/assets/libs/objects/star.dae",
"collision":"/assets/libs/objects/star.stl",
"type":"env",
"material_path":"",
"part_path":"/libs/objects/star.stl",
"fbx":"/home/webservice/server/build/public/4c4f3909-74b0-4206-aec1-fc4acd3a1081/assets/libs/objects/star.fbx",
"solidType":"active",
"isSelect":true
}
]
},
"typedataset":"ObjectDetection",
"models_randomization":{
"loc_range_low":[-1,-1,0],"loc_range_high":[1,1,2]
},
"scene":{
"objects":[
{"name":"floor","collision_shape":"BOX","loc_xyz":[0,0,0],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}},
{"name":"star","collision_shape":"BOX","loc_xyz":[0,0,0.2],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}
],
"lights":[
{"id":1,"type":"SUN","loc_xyz":[5,5,5],"rot_euler":[-0.06,0.61,-0.19],"color_range_low":[0.5,0.5,0.5],"color_range_high":[1,1,1],"energy_range":[2,9]}
]
},
"camera_position":{
"center_shell":[0,0,0],
"radius_range":[0.3,0.65],
"elevation_range":[10,90]
},
"generation":{
"n_cam_pose":3,
"n_sample_on_pose":3,
"n_series":222,
"image_format":"JPEG",
"image_size_wh":[640,480]
}
}
```
В результате работы модуля в папке '/home/user/path/to/dataset' будет создана файловая структура с датасетом.
## Оценка 6D положения объекта (Pose Estimation)
### Создание датасета
Этот этап точно такой же, как и в случае с Object Detection. Так как синтетический датасет формата [BOP](https://github.com/thodan/bop_toolkit/blob/master/docs/bop_datasets_format.md) содержит в аннотации истинные позиции заданных объектов в сцене (ground true pose), поэтому его можно использовать также и при обучения модели [DOPE](https://github.com/NVlabs/Deep_Object_Pose) для оценки 6D положения объекта.
### Обучение модели [DOPE](https://github.com/NVlabs/Deep_Object_Pose/tree/master/train)
Для обучения модели используется скрипт на Python. Аргументом для скрипта является:
- каталог с датасетом, сгенерированный на первом этапе.
В ходе работы скрипта исходный датасет предварительно конвертируется в формат, который используется непосредственно при обучении модели DOPE.
Пример запуска модуля обучения:
```bash
python train_Dope.py --path /home/user/path/to/dataset --epoch 44 --outpath /home/user/path/to/weights --name weightsX
```
- path: путь к каталогу с датасетом
- epoch: количество эпох обучения
- name: наименование файла весов модели на выходе
- outpath: выходной каталог
В результате работы создается файл весов модели с лучшими характеристиками обнаружения weightsX.pth
### Использование навыка в ROS2 для оценки 6D-положения объекта на изображении (runtime)
Этот процесс аналогичен такому же при обнаружении объекта (YoloV8), здесь приведу лишь дерево (bt.xml) и файл описания скилов в дереве (skills.json).
* Папка /path/to/bt/
* bt.xml
```xml
<root BTCPP_format="4">
<BehaviorTree ID="Main">
<Sequence>
<Action ID="RbsAction" do="PoseEstimation" command="peConfigure" sid="a"></Action>
</Sequence>
</BehaviorTree>
</root>
```
* skills.json
```json
{"skills": [
{
"sid": "a",
"SkillPackage": {"name": "Robossembler","version": "1.0","format": "1"},
"Module": {"node_name": "lc_dope","name": "PoseEstimation","description": "Pose Estimation skill with DOPE"},
"BTAction": [
{
"name": "peConfigure",
"type": "run",
"param": [
{
"type": "weights",
"dependency": { "object_name": "knight", "weights_file": "/home/shalenikol/0_rbs/w_knight.pth", "dimensions": [0.03, 0.026, 0.065] }
},
{
"type": "topic",
"dependency": {
"type": "topic",
"topicType": "sensor_msgs/msg/Image",
"topicOut": "/rgbd_camera/image"
},
"isFilled": true
},
{
"type": "topic",
"dependency": {
"type": "topic",
"topicType": "sensor_msgs/msg/CameraInfo",
"topicOut": "/rgbd_camera/camera_info"
},
"isFilled": true
}
],
"result": [],
"typeAction": "ACTION"
}
],
"topicsOut": [
{
"name": "lc_dope/pose_estimation",
"type": "geometry_msgs/msg/Pose"
}
],
"Launch": {
"executable": "pe_dope_lc.py",
"package": "rbss_poseestimation"
},
"Settings": {
"output": {
"params": [
{
"name": "publishDelay",
"value": "0.5"
},
{
"name": "tf2_send_pose",
"value": "1"
},
{
"name": "mesh_scale",
"value": "0.001"
}
]
},
"type": "formBuilder"
}
}
]}
```