3D ml. Часть 1: формы представления 3D-данных

Содержание

Начало работы с OpenMesh

Изначально OpenMesh написан на C++, но имеет обертку на языке Python, которую можно использовать для быстрой и легкой разработки. Давайте посмотрим какие операции предоставляет эта обертка.

Для начала установим пакет с помощью pip:

Создадим новый Python скрипт и импортируем модуль openmesh

Создадим объект, представляющий 3D меш

Добавим несколько вершин

и несколько полигонов

В OpenMesh вершина представлена объектом VertexHandle. Объекты VertexHandle передаются во многие методы библиотеки OpenMesh в качестве параметра.

Есть также альтернативный способ через питоновский список вершин

Стоит отметить, что OpenMesh также вводит специальный тип элемента в модели под названием Half-edge. Я не буду его рассматривать в данной статье. Подробнее о нем можно почитать здесь.

Общие Инструменты

Данная секция содержит в себе общую информацию о Plug-in Manager, Outliner, Hypershade, Center Pivot, World Coordinate System и Working Units, а также Attribute Editor

1.1 Plug-in Manager

Если вам нужно установить плагин, то Plug-in Manager вам в помощь. Данный редактор содержит в себе список плагинов, находящихся в разных секциях, которые видит Maya. Каждая секция — это отдельный путь на файловой системе. Здесь нас интересуют 2 чекбокса: Loaded и Auto Load. Первый отвечает за загрузку плагина в данную сессию, второй же за загрузку плагина при открытии Maya.

Во избежания танцев с бубном из-за различных местоположений ваших плагинов, я советую класть ваши плагины в {MAYA_HOME}/bin/plug-ins
Открыть редактор можно из главного меню: Windows -> Settings/Preferences -> Plug-in Manager

1.2 Outliner

Outliner показывает иерархически список всех объектов в сцене. По умолчанию видны только DAG объекты (остальные скрыты по умолчанию) и не видны шейдеры, материалы и т.п… Для того, чтобы это изменить можно вызвать меню при помощи клика правой кнопкой мыши на Outliner и изменением статуса соответствующих чекбоксов. Пожалуй это самый используемый редактор в Maya, но ему в спину дышит редактор нод — Hypershade

1.3 Hypershade

Главный и основной редактор, если речь заходит о нодах. Hypershade является центральной рабочей областью для шейдинга. Здесь вы можете создавать редактировать и соединяя друг с другом различные ноды\узлы, такие как текстуры, материалы, источники света и т.д.

Открыть его можно:

  1. Нажав на иконку Hypershade в панели инструментов
  2. Из главного меню: Windows > Rendering Editors > Hypershade

Можно выделить следующие примеры использования:

  • Удобно работать со всеми нодами в одном редакторе: легкое переключение между ними, добавление текстур, света, камер и т.п.
  • Все свойства нод легко меняются в Property Editor.
  • Вы можете сразу наблюдать эффект в при изменении материалов в Material Viewer абстрагируясь от вашей 3Д модели

1.4 World Coordinate System и Working Units

Вам может понадобится изменить вертикальную ось, а также меры измерений. Сделать это можно в Windows > Settings/Preferences > Preferences -> SettingsПримеры использования:

  • При импортие, чтобы убедиться, что значения и размеры объектов импортнулись в Maya корректно. Безусловно, метры в сантиметры и наоборот перевести не составит труда. Раскрывается данная функциональность если вы работаете, например с мало используемыми у нас футах, дюймах и т.п.
  • При экспорте: если система, в которую вы, в последующем, будете импортить вашу сцену, должна принимать определенные измерительные единицы, например Unreal Engine 4.

1.5 Center Pivot

Функциональность, которая возвращает пивот (точку опоры) в центр элемента. Относительно этой точки пользователь делает все изменений (смещение, поворот, масштабирование). Крайне полезная функциональность, особенно если вы либо потеряли пивот, либо он находится в неположенном месте. Чтобы вернуть пивот в центр модели нужно использовать Modify -> Center Pivot. К слову, изменить местоположение пивота можно при помощи мыши при зажатой кнопки D на клавиатуре.

1.6 Attribute Editor

Attribute Editor хранит в себе все атрибуты выбранного объекта. Вкладки в верхней части позволяют выбирать узлы (nodes), подключенные к текущему. Здесь вы можете осуществлять все манипуляции с атрибутами ваших объектов. Незаменимая вещь для быстрого доступа к свойствам объекта, хотя большинство манипуляций можно совершать и из Hypershade. Открыть данные редактор можно при помощи Windows > General Editors > Attribute Editor / Windows > UI Elements > Attribute Editor, а также нажатием Ctrl+A (сочетание клавиш по умолчанию)

Воксели (Voxels)

Воксели (от англ. слов volumetric + pixel) являются обобщением пикселей на пространственный случай. Воксельные 3D модели представляют из себя кубические пространственные сетки, в которых объекты представляются множеством маленьких кубиков (вокселей). В компьютере воксели хранятся в виде трехмерной матрицы. Существует ряд форматов, для хранения воксельных моделей, но наиболее распространённым, видимо, является .vox формат. Помимо применения в играх и компьютерной графике в качестве необычного графического стиля (т.н. pixel and voxel art), воксельное представления трехмерных данных часто встречается в медицине и промышленном производстве.

В медицине эта форма данных возникает при работе с томографическими данными, оказывается что среднее значение плотности тканей удобно рассчитывать именно на кубической сетке, а в промышленности, моделирование взаимодействия ЧПУ станка с твердым материалом удобно представлять с помощью булевых операций над двумя множествами, ведь в самом деле, в отличие от полигональных моделей, у воксельных моделей внутреннее пространство не заполнено пустотой, а значит сдвигая или уничтожая отдельные воксели модели, можно моделировать процессы разрушения или деформации твёрдого тела. В самом простом варианте реализации, воксельная модель представляет из себя трехмерный массив, заполненный нулями и единицами (1 — в данной точке пространственной сетке есть воксель, 0 — нет вокселя).

Для вокселизации имеющийся у нас модели воспользуемся встроенным вокселезатором из trimesh:

Out:

К преимуществам воксельного подхода можно отнести:

  • Естественное обобщение подходов, которые применялись для обработки изображений, например трехмерная свертка.
  • Данные для обучения легко получить из любого другого типа моделей.
  • Большая связь с физическими свойствами объектов по сравнению с полигональными и облачными моделями.
  • Возможность представлять воксельные модели в виде обычных векторов.

К недостаткам воксельного подхода можно отнести:

  • “Грубость” аппроксимации формы реальных объектов при малом разрешении.
  • Объём занимаемой воксельными моделями памяти растёт кубически в зависимости от количество интервалов, на которое разбивается каждая ось.

Для того, чтобы визуально оценить качество вокселизации модели в trimesh имеется встроенный интерактивный визуализатор:

С одной стороны, воксельный подход является на сегодняшний день наиболее распространённым из-за простоты его описания, также из-за корпускулярности данная форма наиболее приспособлена для физических симуляций разрушаемых объектов, с другой стороны, данный подход ограничен низким разрешением пространственной сетки. Типичным диапазоном разрешений воксельной сетки является диапазон от до . Несмотря на то, что исследователи пытаются решить проблему низкой размерности, так, например, в авторы использовали октодеревья для построения архитектуры глубокого обучения OGN (Octree Generating Networks), которая позволила работать с сеткой более высокого разрешение чем в предшествующих работах, у данного подхода есть ещё ряд других нерешенных проблем.

Облака точек (Point clouds)

Облако точек является типичной формой данных о пространстве в робототехнике и компьютерном зрении. Физически облако точек представляет собой неупорядоченное множество трехмерных радиус-векторов. Иногда для каждого такого вектора (точки) можно дополнительно указать ее цвет, как дополнительное составляющей не влияющее на геометрию. Такая форма представления пространственных данных часто на практике встречается в задачах сканирования помещений или отдельно взятых объектов. Камеры глубины в качестве результата работы возвращают изображение вместе с его картой глубины (RGBD), что является частным случаем облака точек. Восстановления карты глубины для данного изображения часто называют задачами 2.5D, указывая на то, что, снятый глубинной камерой объект с одного ракурса, не может быть дополнен пространственной информацией с другого ракурса. В этом смысле облако точек содержит в себе больше информации о геометрии объектов чем RGBD изображения.

Примером формата, с помощью которого хранят облака точек является .pcd формат, хотя чаще сканы в виде облака точек хранят в .ply формате. Также стоит отметить, что существует очень удобная, оптимизированная и разнообразная библиотека для обработки данных данного формата — PCL.

Рассматриваемую нами модель кролика в форме облака точек в формате .ply можно найти на официальном сайте стэнфорда:

К преимуществам облака точек можно отнести:

  • Естественный формат данных в задачах пространственного сканирования.
  • Данные данного формата могут быть легко получены из полигональных и функциональных моделей.

К недостаткам облака точек можно отнести:

  • Неупорядоченность данных приводит к проблеме выбора функции ошибки и необходимости разработки специального математического аппарата.
  • Отсутствует информация о связях между точками, что не позволяет корректно восстановить геометрию и топологию исследуемого объекта и требует сложной процедуры постпроцессинга для перевода результата в иные формы представления пространственных данных.

Для того, чтобы работать с облаком точек, можно загрузить .ply модель и создать объект класса PointClud, а можно получить облако точек из текущей .obj модели. Для того, чтобы облако точек, полученное из полигональной модели, было достаточно информативным, необходимо, чтобы точки из которых оно состоит достаточно равномерно и полно покрывали поверхность объекта. Для этого существуют специальные методы сэмплирования точек на поверхности.

Мы можем воспользоваться методом, встроенным в pytorch3d, тем более что он позволяет помимо самих координат точек генерировать и нормали для них:

Визуализируем заданное облакоточек функцией:

Посмотрим на результат визуализации облаков точек для наших моделей (pytorch3d):

Проблема неупорядоченности данных (повернув или отмасштабировав 3D модель, данные её описывающее существенно меняются, при этом по сути модель остаётся прежней) характерна и для полигональных моделей, несмотря на это, облако точек самая редко используемая форма данных в области 3D ML. Если говорить о задаче 2D-to-3D, то изображение в данный формат вообще не принято переводить, вместо этого решают другую задачу PC2Mesh (восстановление полигональной модели из облака точек).

Другие представления

Потоковые сетки хранят грани упорядочено, но независимо, чтобы таким образом сетку можно было пересылать по частям. Порядок граней может быть пространственным, спектральным, или базированным на других свойствах сетки. Потоковые сетки позволяют рендерить очень большие сетки даже тогда, когда они ещё загружаются.

Прогрессивные сетки передают данные о вершинах и гранях с повышающимся уровнем детализации. В отличие от потоковых сеток, прогрессивные сетки дают общую форму целого объекта, но на низком уровне детализации. Дополнительные данные, новые рёбра и грани, прогрессивно увеличивают детализацию сетки.

Нормальные сетки передают постепенные изменения сетки как множество смещений нормалей от базовой сетки. С помощью этой техники, ряд текстур отображает желаемые нарастающие изменения. Нормальные сетки компактны, так как для выражения смещения нужно лишь одно скалярное значение. Однако, техника требует ряд сложных трансформаций чтобы создать текстуры сдвига.

Deep learning и свертки на графах

Чтобы избавиться от ограничений в виде числа параметров и соседей, необходимо работать с целым мешем, а не отдельно составленными патчами. А для построения сложных архитектур нейронных сетей с хорошей обобщающей способностью, надо как-то привести нерегулярное представление меша к регулярному. Во всей области 3D DL существует несколько популярных подходов для этого: вокселизация меша и представление меша как графа.

Так, в работе Mesh Denoising with Facet Graph Convolutions был предложен еще один end-to-end pipeline для устранения шума с помощью представления мешей как графов, только вместо натурального представления графа полигональной сетки (вершины, связанные с вершинами) используется другое – грани, связанные с гранями. Основная идея — сгенерировать граф и запустить на нем сверточную нейронную сеть.

Facet Graph Convolution pipeline

В основе этого метода лежит архитектура U-Net, которой на вход подаются координаты граней и соответствующих нормалей созданного графа, а на выходе получаются скорректированные нормали граней. 

Архитектура Graph Convolution NetworkСвертка графа

Графовое представление и U-Net позволяют учитывать геометрические особенности меша как в локальной структуре (как в предыдущих методах), так и в глобальной.

Зачем нужен mesh denoising?

С помощью технологии трехмерного сканирования можно получить 3D-модель реального объекта. Но знаете ли вы, что почти всегда такие объекты содержат шумы и неточности? В Twin3d мы сканируем людей (и не только) и с помощью фотограмметрии получаем 3D-модели, которые дальше необходимо обрабатывать в зависимости от конечной цели их использования. Естественно, от шумов надо избавляться, чтобы применять виртуальную модель человека в кино/играх/рекламе. Нужно много чего еще делать, но об этом мы поговорим потом.

Сканирование объектов и получение их 3D-моделей используется не только для создания виртуальных людей. Это популярно в reverse engineering для получения CAD-деталей без чертежей, где нужна большая точность реконструкции и шумы недопустимы. Также как людей и CAD-детали, можно сканировать реальные объекты — одежду, обувь, аксессуары, что сейчас очень распространено в связи с созданием виртуальных примерочных. В таких случаях тоже хочется сделать вещь визуально идеальной, поэтому отсканированный объект необходимо обрабатывать.

Процесс устранения шума с 3D-моделей, полученных после сканирования, получил название mesh denoising. Иногда можно встретить слово smoothing, что означает просто «сглаживание». 3D-моделлеры пользуются профессиональным ПО для решения данной задачи, но при этом они тратят достаточно много времени, чтобы убрать все неровности и шероховатости поверхности вручную. А как это делается без вмешательства 3D-моделлера? С помощью методов, которые мы рассмотрим далее.

Соединяем всё вместе

Использование способа с кривой

03 Customize Heart MeshScenesHierarchyCustomHeartChildInspectorMesh FilterHeart MeshChildCustom HeartHeartMeshclone
CustomHeart.csScripts

Inspector

  1. Простая кривая состоит из трёх точек. Задаём точки для первой кривой.
  2. Генерируем первую кривую с помощью и присваиваем её значения . Рисуемая кривая может отображаться в превью, если в качестве последнего параметра указать true.
  1. Задаём точки для второй кривой.
  2. Генерируем вторую кривую с помощью и присваиваем её значения . Рисуемая кривая может отображаться в превью, если в качестве последнего параметра указать true.
  1. Получаем позицию кривой на заданной и умножаем её значение на , чтобы получить .
  2. Создаём новый тип данных для хранения новой позиции текущей вершины и соответствующим образом применяем её Transform.

CustomHeartChildCurve TypeEdit TypeAdd IndicesRemove Indices
Curve TypeCurve1Edit TypeNonePlayCurve Type
Clear Selected VerticesSelected Indices

  • Величина радиуса.
  • Распределение вершин по области.
  • Позиция паттерна выбранных вершин.
  • Способ, выбранный для смещения.

Изменение мешей с помощью Custom Editor

01 Mesh Study DemoScenesScene

EditorProject
MeshInspector.csMeshInspector.cs

MeshStudy.csSaveScriptsMeshStudy.csCubeHierarchy

Клонирование и сброс меша

MeshStudy.csScriptsMeshStudy.cs

  1. Получает исходный меш из компонента .
  2. Копирует в новый экземпляр меша .
  3. Присваивает скопированный меш снова mesh filter.
  4. Обновляет локальные переменные.

HierarchyInspectorMesh Filterclone
MeshInspector.cs

  1. Этот код отрисовывает в Inspector кнопку Reset.
  2. При нажатии он вызывает в MeshStudy.cs функцию .

MeshStudy.cs

  1. Проверка существования исходного и клонированного меша.
  2. Сброс на исходный меш.
  3. Присвоение .
  4. Обновление локальных переменных.

InspectorTest EditReset

Отображение вершин

MeshInspector.cs

  1. получает из значения Transform.
  2. получает режим Rotation текущего шарнира.
  3. Обходим вершины меша и отрисовываем точки с помощью .
  1. Задаёт цвет, размер и позицию точки с помощью вспомогательного класса .
  2. создаёт манипулятор неограниченного движения, упрощающий операцию перетаскивания, которая пригодится нам в следующем разделе.

InspectorMove Vertex Point

Перемещение отдельной вершины

MeshInspector.cs

  1. отслеживает все изменения, происходящие с точками, и хорошо работает вместе с для распознавания операции перетаскивания.
  2. Для перетаскиваемой вершины функция получает в качестве параметров её индекс и значения Transform. Так как значения Transform вершины находятся в мировом пространстве, мы преобразуем их в локальное пространство с помощью .

MeshStudy.cs

  1. Мы обновляем целевую вершину значением .
  2. Присваиваем значения обновлённых вершин обратно .
  3. В пересчитываем и перерисовываем меш, чтобы он соответствовал изменениям.

Нахождение всех похожих вершин

MeshStudy.cs

Inspector

InspectorMesh Studyvertices
MeshStudy.csвесь

  1. получаем позицию целевой вершины, которая будет использоваться в качестве аргумента метода .
  2. Этот метод возвращает список индексов (соответствующих вершинам), имеющих ту же позицию, что и целевая вершина.
  3. Цикл обходит весь список и присваивает соответствующим вершинам значение .
  4. Присваиваем обновлённый обратно . Затем вызываем для перерисовки меша с новыми значениями.

Сводка представлений сеток

Операция Вершинное представление Список граней «Крылатое» представление
V-V Все вершины вокруг вершины Явно V → f1, f2, f3, … → v1, v2, v3, … V → e1, e2, e3, … → v1, v2, v3, …
E-F Все рёбра грани F(a, b,c) → {a, b}, {b, c}, {a, c} F → {a, b}, {b, c}, {a, c} Явно
V-F Все вершины грани F(a, b,c) → {a, b,c} Явно F → e1, e2, e3 → a, b, c
F-V Все грани вокруг вершины Поиск пары Явно V → e1, e2, e3 → f1, f2, f3, …
E-V Все рёбра вокруг вершины V → {v, v1}, {v, v2}, {v, v3}, … V → f1, f2, f3, … → v1, v2, v3, … Явно
F-E Обе грани ребра Сравнение списков Сравнение списков Явно
V-E Обе вершины ребра E(a, b) → {a, b} E(a, b) → {a, b} Явно
Flook Найти грань с данными вершинами F(a, b,c) → {a, b,c} Пересечение множеств v1,v2,v3 Пересечение множеств v1,v2,v3
Размер памяти V*avg(V,V) 3F + V*avg(F,V) 3F + 8E + V*avg(E,V)
Пример с 10 вершин, 16 граней, 24 ребра:
10 * 5 = 50 3*16 + 10*5 = 98 3*16 + 8*24 + 10*5 = 290
Рисунок 5: сводка операций представлений сеток

В представленной выше таблице, явно указывает на то, что операция может быть выполнена за постоянное время, так как хранятся непосредственные данные; сравнение списков указывает на то, что для выполнения операции должно быть выполнено сравнение двух списков; и поиск пары указывает на то, что должен быть выполнен поиск двух индексов. Обозначение avg(V,V) означает среднее число вершин, соединённых с заданной вершиной; avg(E,V) означает среднее число рёбер соединённых с заданной вершиной, и avg(F,V) — среднее число граней, соединённых с заданной вершиной.

Обозначение «V → f1, f2, f3, … → v1, v2, v3, …» показывает что для выполнения операции необходим обход вокруг нескольких элементов. К примеру, чтобы получить «все вершины вокруг заданной вершины V» используя список граней, нужно сначала найти грани вокруг заданной вершины V используя список вершин. Затем, из этих граней, используя список граней, найти вершины вокруг них. Заметьте, что «крылатое» представление хранит почти всю информацию в явном виде, и другие операции всегда обходят сначала ребро, чтобы получить дополнительную информацию. Вершинное представление — единственное представление, которое в явном виде хранит соседние вершины заданной вершины.

С увеличением сложности представлений (слева направо в сводке), количество информации, хранящейся в явном виде, растёт. Это даёт более прямой, постоянный по времени, доступ к обходу и топологии различных элементов, но ценой увеличения занимаемой памяти для сохранения индексов надлежащим образом.

Как общее правило, сетки использующие список граней используются всякий раз, когда объект должен рендериться с помощью аппаратного обеспечения, которое не меняет геометрию (соединения), но может деформировать или трансформировать (позиции вершин), например в рендеринге статичных или трансформируемых объектов в реальном времени. «Крылатое» представление используется когда геометрия изменяется, например в интерактивных пакетах моделирования или для вычисления подразделённых поверхностей. Вершинное представление идеально для эффективных, комплексных изменений в геометрии или топологии, пока аппаратный рендеринг не важен.

Элементы моделирования сетки

Объекты, созданные с помощью полигональных сеток, должны хранить разные типы элементов, такие как вершины, рёбра, грани, полигоны и поверхности. Во многих случаях хранятся лишь вершины, рёбра и либо грани, либо полигоны. Рендерер может поддерживать лишь трёхсторонние грани, так что полигоны должны быть построены из их множества, как показано на рис. 1. Однако многие рендереры поддерживают полигоны с четырьмя и более сторонами, или умеют триангулировать полигоны в треугольники на лету, делая необязательным хранение сетки в триангулированной форме. Также в некоторых случаях, таких как моделирование головы, желательно уметь создавать и трёх- и четырёхсторонние полигоны.

Вершина — это позиция вместе с другой информацией, такой как цвет, вектор нормали и координаты текстуры. Ребро — это соединение между двумя вершинами. Грань — это замкнутое множество рёбер, в котором треугольная грань имеет три ребра, а четырёхугольная — четыре. Полигон — это набор компланарных (лежащих в одной плоскости) граней. В системах, которые поддерживают многосторонние грани, полигоны и грани равнозначны. Однако, большинство аппаратного обеспечения для рендеринга поддерживает лишь грани с тремя или четырьмя сторонам, так что полигоны представлены как множество граней. Математически, полигональная сетка может быть представлена в виде неструктурированной сетки, или неориентированного графа, с добавлением свойств геометрии, формы и топологии.

Поверхности, чаще называемые группами сглаживания, полезны, но не обязательны для группирования гладких областей. Представьте себе цилиндр с крышками, такой как жестяная банка. Для гладкого затенения сторон, все нормали должны указывать горизонтально от центра, тогда как нормали крышек должны указывать в +/-(0,0,1) направлениях. Если рендерить как единую, затенённую по Фонгу поверхность, вершины складок имели бы неправильные нормали. Поэтому, нужен способ определения где прекращать сглаживание для того, чтобы группировать гладкие части сетки, также, как полигоны группируют трёхсторонние грани. Как альтернатива предоставлению поверхностей/групп сглаживания, сетка может содержать другую информацию для расчёта тех же данных, такая как разделяющий угол (полигоны с нормалями выше этого предела либо автоматически рассматриваются как отдельные группы сглаживания, либо по отношению к ребру между ними применяется какая-либо техника, как например разделение или скашивание). Также, полигональные сетки с очень высоким разрешением менее подвержены проблемам, для решения которых требуются группы сглаживания, так как их полигоны настолько малы, что нужда в них пропадает. Кроме того, альтернатива существует в возможности просто отсоединения самих поверхностей от оставшейся части сетки. Рендереры не пытаются сглаживать рёбра между несмежными полигонами.

Формат полигональной сетки может определять и другие полезные данные. Могут быть определены группы, которые задают отдельные элементы сетки и полезны для установления отдельных подобъектов для скелетной анимации или отдельных субъектов нескелетной анимации. Обычно определяются материалы, позволяя разным частям сетки использовать разные шейдеры при рендере. Большинство форматов сетки также предполагают UV координаты, которые являются отдельным двухмерным представлением полигональной сетки, «развёрнутым» чтобы показать какая часть двумерной текстуры применяется к разным полигонам сетки.

Манипуляция с отображением текстуры и координатами вершин

Я не буду раскрывать тему отображения текстуры (texture mapping) полигонов. Читатель может прочитать детальное объяснение этой темы здесь.

Получим координаты текстуры (UV texture coordinates) вершины:

tc представляет собой tuple. Значения координат u и v можно получить по индексу 0 и 1 соответственно.

Изменим координаты текстуры

Здесь vh — объект типа VertexHandle.

Получим точку с координатами вершины

point представляет собой tuple. Координаты точки можно получить по индексу 0 и 1

Можно получить все точки вершин модели

и использовать их для сдвига модели вдоль оси (например X)

Важные замечания по работе с OpenMesh

Не советую использовать enumerate() при итерировании вершин в цикле. Вы можете получить неожиданное поведение, например одинаковые координаты текстуры UV для разных вершин.

При сохранение меша в файл OpenMesh по умолчанию не сохраняет координаты текстур для вершин (vt строки) в файле obj. Чтобы решить эту проблему нужно передать параметр vertex_tex_coord в метод write_mesh (источник):

Также OpenMesh не сохраняет файл материалов mtl в файле obj. Для сохранения информации о материале используйте параметр face_color при чтении файла obj

и записи в файл

То же касается и нормалей. Чтение модели obj с нормалями

и записи в файл

Здесь важно использовать одинаковые параметры и при чтении и при записи. Например, если мы хотим получить и сохранить информации о материале нужно использовать параметр face_color в обоих методах read_trimesh и write_mesh

При работе с OpenMesh я сделал интересное наблюдение: порядок индексов координат текстур вершин (индексы строк vt) меняется. Например для такой строки в исходном файле obj

Соответствующая строка в выходном файле obj может выглядеть примерно так

С чего все начиналось

Когда-то были фильтры… Просто сглаживающие фильтры, которые берут координаты вершин меша и усредняют по соседним вершинам (Laplacian smoothing, Taubin smoothing).

Laplacian smoothing

В 2003 году появляется Bilateral mesh denoising – расширение билатерального фильтра (который использовался для сглаживания шума на 2D картинках) на трехмерные полигональные сетки. Суть остается та же – усредняются координаты вершин, но уже немного умнее: используются при этом как координаты вершин, так и нормали вершин. Еще через 7 лет придумали применять такой билатеральный фильтр не к вершинам, а к нормалям граней (Bilateral normal filtering for mesh denoising), что значительно увеличило качество сглаживания.

Итеративный процесс вычисления новой нормали с помощью Bilateral Normal Filtering заключается в следующем:

где — набор соседних граней для грани , — нормаль грани , — площадь грани , — центроид грани (точка пересечения медиан треугольника), — гауссиана, — оператор нормализации.

Билатеральный фильтр является средним взвешенным с весом, состоящим из нескольких частей. — для грани определяет значимость грани в терминах удаленности друг от друга — чем больше расстояние, тем меньше вес. Аналогично с , только на вес влияет не расстояние между гранями, а разница между векторами нормалей грани. Также учитывается значение площади грани

В 2015 году улучшают подход с билатеральными фильтрами с появлением Guided Mesh Normal Filtering, где используется направляющая нормаль для сглаживания.

Чего хотели добиться улучшением билатеральных фильтров? Чтобы не сглаживать все подряд, а оставлять достаточно резкими детали меша, которые должны быть резкими. При этом для каждой 3D-модели пользователю необходимо подбирать параметры алгоритмов, чтобы добиться удовлетворительных результатов.

Наряду с фильтрами развивались подходы mesh denoising, основанные на оптимизации. Так, например, в работе Mesh Denoising via L0 minimization авторы максимизируют плоские поверхности меша и постепенно устраняют шум, не сглаживая при этом углы. Данный подход хорош в случаях, когда все отсканированные объекты – CAD-модели с правильными геометрическими формами.

Заключение

Интересно наблюдать, как эволюционируют подходы обработки 3D моделей с развитием технологий. Когда-то обычные сглаживающие фильтры были пиком совершенства, сейчас же все по-другому: появляются интересные статьи, в которых ручная обработка мешей заменяется автоматической с помощью нейронных сетей и глубокого обучения. 

На данный момент в задаче mesh denoising, и, в общем, в задачах обработки полигональных сеток, все большую популярность приобретают подходы с графовым представлением мешей, с помощью которого можно учитывать как локальную (в пределах одной грани), так и глобальную структуру меша. 

В Twin3d мы занимаемся разными задачами, и mesh denoising входит в их число. В будущих статьях будем рассказывать уже о своих разработках, не пропустите 😉