Страница 1 из 1

Построение карты высот: решения, особенности, плюсы и минусы

Добавлено: 15 апр 2016, 15:26
dadreamer
Несколько лет назад я приступал к этому вопросу, но так тогда до конца и не довёл решение по разным причинам. Сейчас вот решил снова этим заняться, пока есть немного свободного времени. Да и хочется всё-таки сделать нормальную визуализацию в будущих проектах. Естественно, речь о :labview: . В общем, есть глобальная задача, связанная с 3D-реконструкцией. А её небольшая часть - построение 3D-карты (поля) высот по 2D-массиву пикселей, где яркость каждого пикселя (U8 / U16) представляет собой относительную высоту (координата Z), а положение пикселя в массиве (строка, столбец) - это координаты Y и X соответственно. Эта небольшая подзадача легко решаема (что я покажу ниже), но есть кое какие нюансы, которые хотелось бы уточнить. Сначала рассмотрим все доступные варианты.

Решение 1 (очевидное) - использование инструментов 3D Picture Control.
В принципе, всё просто - создаём сцену (Create Object) и загоняем на неё наше поле высот, полученное из 2D-массива через Create Height Field. В итоге имеем что-то такое:
LV_3D_init_pos.jpg
2016-04-15_15-54-25.jpg
Видео:
kzfVagr1ZSM

Решение 2 (также довольно очевидное) - использование инструмента 3D Graph -> Surface.
Здесь всё ещё проще - помещаем на FP график 3D Surface из палитры 3D Graph, на BD загоняем в Plot Helper наш 2D-массив. Если хорошенько поднастроить внешний вид графика (отключить оси и т.п.), то получится следующее:
LV_3D_Surface.jpg
2016-04-15_16-01-03.jpg
2016-04-15_16-01-03.jpg (36.17 КБ) 6119 просмотров
Видео:
1cRT3LYYVtU

Решение 3 (уже не такое очевидное) - использование сторонних инструментов для визуализации.
В этом плане очень сложно сделать хороший выбор. Я выбрал среду машинного зрения HALCON от компании MVTec, просто потому что раньше пользовался ей и в ней есть поддержка .NET/ActiveX. Среда отнюдь не бесплатная, но она стоит своих денег. Используем в :labview: внешнюю процедуру visualize_object_model_3d, которую запускаем с помощью .NET узлов. Оставляя за кадром технические детали реализации, покажу сразу картинки:
Halcon_3D_init_pos.jpg
2016-04-15_16-13-23.jpg
2016-04-15_16-13-23.jpg (41.99 КБ) 6119 просмотров
Видео:
ZTuQRJDP2L8
(Если кому-то станет интересно и он решит протестировать HALCON в триал-режиме или даже купить, то я выложу :vi: , использовавшийся для вызова процедуры.)

Теперь, собственно, мои замечания.

Решение 1.
1) Насколько я понимаю, инструмент Create Height Field строит классическую карту высот, т.е. набор точек (вертексов), соединённых между собой (аналог terrain в 3D-моделировании). Временами получается красиво, временами нет. Я не нашёл способа отключить этот "частокол", т.е. сделать так, чтобы отображались только точки, без соединяющих связей.
2) Плохо, что вручную нужно выставлять положение камеры. Признаю, долго подбирал такие координаты, чтобы меня устраивала исходная позиция объекта. И я не совсем уверен, что такие координаты подойдут для другого объекта. В принципе, можно рассчитывать каждый раз положение камеры по геометрическим параметрам объекта. Но это, опять же, лишняя работа. А магической опции "поместить в центр и отдалить камеру" нигде нет. :( Также совсем неочевидна связь параметра ModelView Matrix и исходного положения (Camera Position, Target, Up Direction). В сети есть :vi: , преобразующий ModelView Matrix, но в итоге реально получаем только один кластер - Camera Position. Как рассчитать другие два - :dntknw:
3) Не понятно, как окрасить модель в градиент. Одним цветом, к сожалению, плохо передаётся глубина объекта. А с градиентом становится и красиво, и информативно. Если только применить текстуру на объект, но её сначала нужно создать, либо загрузить из файла. Короче, опять лишняя работа.
4) Не совсем представляю, как исключить нулевые точки из построения. Слева/справа ещё можно обрезать. А что делать там, где находится полезная информация...
5) На LV 2014 64-bit как-то глючит: рисует артефакты по всему экрану, хотя должен рендерить сугубо в своё окошко. Надо проверить на 2015.

Решение 2.
Это решение понравилось даже больше, чем предыдущее. Однако осталась проблема 1, хотя на неё можно при желании забить. Проблема 2 решена - объект всегда помещён по центру, а камера отдалена так, как нужно. :super: Проблема 3 решена - можем выбрать любой градиент, как душе угодно. Проблема 4 осталась, но теперь она менее выражена - мы можем окрасить нулевые точки цветом фона (чёрным, например) и тогда они будут почти не видны (иногда можно увидеть в некоторых позициях).
1) Вторая проблема решилась, но породила другую - объект всегда по центру, сдвинуть его мы не можем. :D При сдвиге он возвращается на своё место. Это мешает разглядывать детали.
2) При длительном использовании графика (открытие свойств, вращение/зуммирование объекта) может либо зависнуть, либо вылететь :labview: :shok: Правда, я это мало тестировал, надо будет на последних версиях проверить.
3) В ран-тайме недоступен рендер в отдельное окно (в отличие от 3D Picture и HALCON). Хотя в отладке этот режим есть. Может, как-то включается, не нашёл.
А так, решение вроде бы удачное. Если пренебречь описанными траблами, то можно использовать.

Решение 3.
Хорошее решение, удовлетворяет большинство моих запросов. Решены проблемы 1, 2, 3 и 4. Однако, кое что стоит отметить.
1) Оператор gen_object_model_3d_from_points создаёт не карту высот (height map), а облако точек (point field). То есть, получаем несвязанные между собой точки (вертексы). Это удобно в большинстве случаев. Но если вдруг потребуется карта высот, то не совсем понятно, как на неё переключиться. Проблема, скорее, надуманная, ибо сам не решил, что мне будет удобнее. Да и с имеющимся функционалом HALCON'а решение найти не составит труда.
2) Продукт платный, что вызывает естественные сложности с лицензированием, распространением и т.д. Известная в таких случаях проблема.
3) Интерфейс ActiveX какой-то глючный, техподдержка не советует его использовать. Рекомендуют работать на .NET. Что вызывает жёсткую привязку к .NET Framework и его библиотекам. Можно, конечно, попробовать DLL, но такой подход имеет ряд минусов (типа отсутствия встроенного окна HALCON на панели LabVIEW).

Все три решения имеют ещё один общий минус. Так как везде используется OpenGL, а когда его нет - программная обработка, то на слабых машинах (в т.ч. со встроенной видяхой) визуализация заметно подтормаживает. Хотя таких машин всё меньше становится с каждым годом. Современные компы спокойно тянут обработку сотен тысяч точек.

Возможны так же какие-то альтернативные решения. Беглый поиск в гугле мало что дал, но может кто-то уже применял подобные альтернативы или видел подходящие тулкиты... Я когда-то пробовал приспособить под это дело движок Irrlicht, но дальше копания в примерах у меня дело не пошло. Знаю, что можно реализовать многое с нуля, например тот же OpenGL прикрутить, но сейчас абсолютно нет никакого желания и времени, чтобы писать обёртки, разбираться в вызовах библиотек и прочее. Интересуют только готовые решения для LabVIEW. В общем, интересно, кто и как решает похожие задачи 3D-визуализации.

Re: Построение карты высот: решения, специфика, особенности

Добавлено: 15 апр 2016, 22:50
Artem.spb
мои три копейки
dadreamer писал(а): Решение 1.
1) Насколько я понимаю, инструмент Create Height Field строит классическую карту высот, т.е. набор точек (вертексов), соединённых между собой (аналог terrain в 3D-моделировании). Временами получается красиво, временами нет. Я не нашёл способа отключить этот "частокол", т.е. сделать так, чтобы отображались только точки, без соединяющих связей.
как-то так
3d1.png
draw mode: points
2) Плохо, что вручную нужно выставлять положение камеры. Признаю, долго подбирал такие координаты, чтобы меня устраивала исходная позиция объекта. И я не совсем уверен, что такие координаты подойдут для другого объекта. В принципе, можно рассчитывать каждый раз положение камеры по геометрическим параметрам объекта. Но это, опять же, лишняя работа. А магической опции "поместить в центр и отдалить камеру" нигде нет. :(
однако есть
3d2.png
3d2.png (7.91 КБ) 6103 просмотра

Также совсем неочевидна связь параметра ModelView Matrix и исходного положения (Camera Position, Target, Up Direction). В сети есть :vi: , преобразующий ModelView Matrix, но в итоге реально получаем только один кластер - Camera Position. Как рассчитать другие два - :dntknw:
довольно очевидно, что смотреть стоит в центр объекта (масс, геометрический, какой угодно)
и головой вверх, ногами вниз. т.е. нет смысла без необходимости переворачивать камеру вверх ногами.
3) Не понятно, как окрасить модель в градиент. Одним цветом, к сожалению, плохо передаётся глубина объекта. А с градиентом становится и красиво, и информативно. Если только применить текстуру на объект, но её сначала нужно создать, либо загрузить из файла. Короче, опять лишняя работа.
на форуме NI народ извращается, детально не смотрел
4) Не совсем представляю, как исключить нулевые точки из построения. Слева/справа ещё можно обрезать. А что делать там, где находится полезная информация...
это я не понял
5) На LV 2014 64-bit как-то глючит: рисует артефакты по всему экрану, хотя должен рендерить сугубо в своё окошко. Надо проверить на 2015.
2014/32 глюков не наблюдал, толко кошмарное качество больших объектов, но всё в рамках 3Д индикатора.

вот как выглядит точечное колесо после волшебной кнопки
3d3.png
В приложении код этого самого примера. Насчёт текстур не знаю, код выдрал из своего проекта. Без чего можно обойтись, не проверял.

Re: Построение карты высот: решения, специфика, особенности

Добавлено: 16 апр 2016, 16:53
dadreamer
Artem.spb писал(а):
dadreamer писал(а):Решение 1.
1) Насколько я понимаю, инструмент Create Height Field строит классическую карту высот, т.е. набор точек (вертексов), соединённых между собой (аналог terrain в 3D-моделировании). Временами получается красиво, временами нет. Я не нашёл способа отключить этот "частокол", т.е. сделать так, чтобы отображались только точки, без соединяющих связей.
draw mode: points
Большое спасибо! Не думал, что можно поточечно Mesh построить. Использовал Create Mesh With Attributes, получилось как-то так:
2016-04-16_18-23-53.jpg
Картинку модели уж приводить не буду, получилось нормальное облако точек. Что теперь хорошо - я могу не строить нулевые точки (цикл For в начале диаграммы). С освещением только пока не разобрался. Сверху точки окрашены в выбранный мной цвет, переворачиваю модель - цвет становится почти чёрный. Как сделать одинаковый окрас во всех позициях? Источник света нужно ставить?..
Artem.spb писал(а):
dadreamer писал(а):2) Плохо, что вручную нужно выставлять положение камеры. Признаю, долго подбирал такие координаты, чтобы меня устраивала исходная позиция объекта. И я не совсем уверен, что такие координаты подойдут для другого объекта. В принципе, можно рассчитывать каждый раз положение камеры по геометрическим параметрам объекта. Но это, опять же, лишняя работа. А магической опции "поместить в центр и отдалить камеру" нигде нет. :(
однако есть
Вот за это отдельное спасибо! :super: Что-то я проглядел этот метод. Смотрел в основном на свойства контрола. Реально работает, можно не париться с положением камеры.
Artem.spb писал(а):
dadreamer писал(а):Также совсем неочевидна связь параметра ModelView Matrix и исходного положения (Camera Position, Target, Up Direction). В сети есть :vi: , преобразующий ModelView Matrix, но в итоге реально получаем только один кластер - Camera Position. Как рассчитать другие два - :dntknw:
довольно очевидно, что смотреть стоит в центр объекта (масс, геометрический, какой угодно)
и головой вверх, ногами вниз. т.е. нет смысла без необходимости переворачивать камеру вверх ногами.
Ну, это да, согласно этому правилу я и выставлял положение камеры. Я к тому, что в реальном времени, вращая/зуммируя/перетаскивая модель, мы меняем её положение и положение камеры. Получить текущие координаты можно только с помощью свойства ModelView Matrix. Оно связано с Camera Position, Target, Up Direction, но получить из одного другое не так просто. Один параметр я вытащил, остальные два - нет. Мне кажется, NI могли бы сделать эту работу за пользователя, странно, что это до сих пор не реализовано как отдельное свойство/метод.
Artem.spb писал(а):
dadreamer писал(а):3) Не понятно, как окрасить модель в градиент. Одним цветом, к сожалению, плохо передаётся глубина объекта. А с градиентом становится и красиво, и информативно. Если только применить текстуру на объект, но её сначала нужно создать, либо загрузить из файла. Короче, опять лишняя работа.
на форуме NI народ извращается, детально не смотрел
Так там экспериментируют с графиками из палитры 3D Graph, а не с 3D Picture Control. Причём примеры приведены на старых версиях графиков, работающих на ComponentWorks ActiveX. Как я выше писал, градиент прекрасно устанавливается на 3D графики. А вот с 3D Picture Control загвоздка.
Artem.spb писал(а):
dadreamer писал(а):4) Не совсем представляю, как исключить нулевые точки из построения. Слева/справа ещё можно обрезать. А что делать там, где находится полезная информация...
это я не понял
Вариант с Mesh'ем решил эту проблему (см. код выше). Просто в исходных картинках обязательно есть пиксели с нулевой яркостью. Такие пиксели не несут никакой информации, строить по ним вертексы не нужно. Потому я такие пиксели фильтрую. В принципе, можно установить порог по яркости и выше, единиц 20-30, если захочется.
Artem.spb писал(а):
dadreamer писал(а):5) На LV 2014 64-bit как-то глючит: рисует артефакты по всему экрану, хотя должен рендерить сугубо в своё окошко. Надо проверить на 2015.
2014/32 глюков не наблюдал, толко кошмарное качество больших объектов, но всё в рамках 3Д индикатора.
Проверил сегодня на LV 2015 SP1 64-bit - артефактов нет, всё в порядке. Видимо, проблема была только в 2014-й версии на 64 бита. Проверял на других :labview: на 32 бита, тоже всё нормально.

В общем, благодаря советам Artem.spb удалось решить большую часть проблем, связанных с 3D Picture Control. Осталось разобраться с цветами и всё-таки как-то задать градиент. Я вижу, у вас текстура из файла грузится. Она готовая у вас или вы её отдельно как-то генерируете?

Re: Построение карты высот: решения, специфика, особенности

Добавлено: 16 апр 2016, 17:38
Artem.spb
dadreamer писал(а):С освещением только пока не разобрался. Сверху точки окрашены в выбранный мной цвет, переворачиваю модель - цвет становится почти чёрный. Как сделать одинаковый окрас во всех позициях? Источник света нужно ставить?.
освещение - это что-то адовое. Там дофига параметров и не очень понятно, как они работают. Есть некий параметр "равномерно со всех сторон", но результат он мне дал вовсе не тот, что я ожидал (никакой равномерности). В итоге я экспериментально подобрал настройки источников.

Artem.spb писал(а):Получить текущие координаты можно только с помощью свойства ModelView Matrix. Оно связано с Camera Position, Target, Up Direction, но получить из одного другое не так просто. Один параметр я вытащил, остальные два - нет. Мне кажется, NI могли бы сделать эту работу за пользователя, странно, что это до сих пор не реализовано как отдельное свойство/метод.
Согласен. Я тоже смог определить только положение камеры. Но в итоге имеющиеся задачи решались другими способами, поэтому я не парился.
3) Не понятно, как окрасить модель в градиент. Одним цветом, к сожалению, плохо передаётся глубина объекта. А с градиентом становится и красиво, и информативно.
Ну с ходу приходит в голову идея разделить точки на группы и каждой группе свой цвет отрисовки назначить. Опять же через одно место, но других вариантов не знаю.
Я вижу, у вас текстура из файла грузится. Она готовая у вас или вы её отдельно как-то генерируете?
там сложная модель собирается из деталей. Рама на колёсах катается по рельсам. К сожалению, заказчик попросил удалить видео с ютуба.
Отдельный части загружаются из независимых Файлов. Модели рисовались в солиде, потом экспортировались в то, что :labview: понимает. Задачи обновлять их постоянно не стояло, только вращать и перемещать. Ну и ещё цвет менять (лампочка вкл/выкл).

Re: Построение карты высот: решения, особенности, плюсы и ми

Добавлено: 21 апр 2016, 12:35
dadreamer
Продолжаю свои эксперименты.
dadreamer писал(а):С освещением только пока не разобрался. Сверху точки окрашены в выбранный мной цвет, переворачиваю модель - цвет становится почти чёрный. Как сделать одинаковый окрас во всех позициях? Источник света нужно ставить?..
Как оказалось, нужно просто выключить освещение: SceneObject.Specials.Lighting = Off. Теперь во всех положениях точки модели имеют одинаковый цвет и яркость.
dadreamer писал(а):Осталось [...] всё-таки как-то задать градиент.
Сперва попробовал самостоятельно создать градиентный массив - при применении на объект получилась фигня. :) Потом нашёл вот такой :vi: : https://decibel.ni.com/content/docs/DOC-9294 Подходит как раз на 8-битный объект и можно сколько угодно задать цветов для перехода. При создании Mesh-объекта ставим Color Binding Mode = Per Vertex. Работает очень хорошо:
2016-04-21_14-18-15.jpg
Snippet.png
3d_test_in_lv_3.vi
lv2011
(51.55 КБ) 236 скачиваний
Так что, в принципе, все описанные выше неприятности с 3D Picture Control удачно разрешились. Это относится к режиму "облако точек". Для режима "поле высот" цвета отдельных вертексов не выставляются. Но можно применить текстуру, полученную наложением градиента на яркости пикселей объекта:
2016-04-22_12-36-15.jpg
Snippet.png
3d_test_in_lv.vi
lv2011
(49.65 КБ) 227 скачиваний
Ещё бы как-то сглаживание применить, а то местами выглядит как в игре с низким разрешением. Ну, и остаётся минус с невозможностью отсечения нулевых точек. Но, в общем и целом, задача построения карты высот и облака точек в :labview: достигнута.

Покопался также немного в Halcon'е. Так и не нашёл простого метода для конвертации "облако точек" -> "карта высот". Есть вариант с триангуляцией облака по нормалям, но он медленный и изменяет модель. Не совсем мне понравилось. Буду ещё экспериментировать.