Построение карты высот: решения, особенности, плюсы и минусы
Добавлено: 15 апр 2016, 15:26
Несколько лет назад я приступал к этому вопросу, но так тогда до конца и не довёл решение по разным причинам. Сейчас вот решил снова этим заняться, пока есть немного свободного времени. Да и хочется всё-таки сделать нормальную визуализацию в будущих проектах. Естественно, речь о . В общем, есть глобальная задача, связанная с 3D-реконструкцией. А её небольшая часть - построение 3D-карты (поля) высот по 2D-массиву пикселей, где яркость каждого пикселя (U8 / U16) представляет собой относительную высоту (координата Z), а положение пикселя в массиве (строка, столбец) - это координаты Y и X соответственно. Эта небольшая подзадача легко решаема (что я покажу ниже), но есть кое какие нюансы, которые хотелось бы уточнить. Сначала рассмотрим все доступные варианты.
Решение 1 (очевидное) - использование инструментов 3D Picture Control.
В принципе, всё просто - создаём сцену (Create Object) и загоняем на неё наше поле высот, полученное из 2D-массива через Create Height Field. В итоге имеем что-то такое: Видео:
kzfVagr1ZSM
Решение 2 (также довольно очевидное) - использование инструмента 3D Graph -> Surface.
Здесь всё ещё проще - помещаем на FP график 3D Surface из палитры 3D Graph, на BD загоняем в Plot Helper наш 2D-массив. Если хорошенько поднастроить внешний вид графика (отключить оси и т.п.), то получится следующее: Видео:
1cRT3LYYVtU
Решение 3 (уже не такое очевидное) - использование сторонних инструментов для визуализации.
В этом плане очень сложно сделать хороший выбор. Я выбрал среду машинного зрения HALCON от компании MVTec, просто потому что раньше пользовался ей и в ней есть поддержка .NET/ActiveX. Среда отнюдь не бесплатная, но она стоит своих денег. Используем в внешнюю процедуру visualize_object_model_3d, которую запускаем с помощью .NET узлов. Оставляя за кадром технические детали реализации, покажу сразу картинки: Видео:
ZTuQRJDP2L8
(Если кому-то станет интересно и он решит протестировать HALCON в триал-режиме или даже купить, то я выложу , использовавшийся для вызова процедуры.)
Теперь, собственно, мои замечания.
Решение 1.
1) Насколько я понимаю, инструмент Create Height Field строит классическую карту высот, т.е. набор точек (вертексов), соединённых между собой (аналог terrain в 3D-моделировании). Временами получается красиво, временами нет. Я не нашёл способа отключить этот "частокол", т.е. сделать так, чтобы отображались только точки, без соединяющих связей.
2) Плохо, что вручную нужно выставлять положение камеры. Признаю, долго подбирал такие координаты, чтобы меня устраивала исходная позиция объекта. И я не совсем уверен, что такие координаты подойдут для другого объекта. В принципе, можно рассчитывать каждый раз положение камеры по геометрическим параметрам объекта. Но это, опять же, лишняя работа. А магической опции "поместить в центр и отдалить камеру" нигде нет. :( Также совсем неочевидна связь параметра ModelView Matrix и исходного положения (Camera Position, Target, Up Direction). В сети есть , преобразующий ModelView Matrix, но в итоге реально получаем только один кластер - Camera Position. Как рассчитать другие два -
3) Не понятно, как окрасить модель в градиент. Одним цветом, к сожалению, плохо передаётся глубина объекта. А с градиентом становится и красиво, и информативно. Если только применить текстуру на объект, но её сначала нужно создать, либо загрузить из файла. Короче, опять лишняя работа.
4) Не совсем представляю, как исключить нулевые точки из построения. Слева/справа ещё можно обрезать. А что делать там, где находится полезная информация...
5) На LV 2014 64-bit как-то глючит: рисует артефакты по всему экрану, хотя должен рендерить сугубо в своё окошко. Надо проверить на 2015.
Решение 2.
Это решение понравилось даже больше, чем предыдущее. Однако осталась проблема 1, хотя на неё можно при желании забить. Проблема 2 решена - объект всегда помещён по центру, а камера отдалена так, как нужно. Проблема 3 решена - можем выбрать любой градиент, как душе угодно. Проблема 4 осталась, но теперь она менее выражена - мы можем окрасить нулевые точки цветом фона (чёрным, например) и тогда они будут почти не видны (иногда можно увидеть в некоторых позициях).
1) Вторая проблема решилась, но породила другую - объект всегда по центру, сдвинуть его мы не можем. При сдвиге он возвращается на своё место. Это мешает разглядывать детали.
2) При длительном использовании графика (открытие свойств, вращение/зуммирование объекта) может либо зависнуть, либо вылететь Правда, я это мало тестировал, надо будет на последних версиях проверить.
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-визуализации.
Решение 1 (очевидное) - использование инструментов 3D Picture Control.
В принципе, всё просто - создаём сцену (Create Object) и загоняем на неё наше поле высот, полученное из 2D-массива через Create Height Field. В итоге имеем что-то такое: Видео:
kzfVagr1ZSM
Решение 2 (также довольно очевидное) - использование инструмента 3D Graph -> Surface.
Здесь всё ещё проще - помещаем на FP график 3D Surface из палитры 3D Graph, на BD загоняем в Plot Helper наш 2D-массив. Если хорошенько поднастроить внешний вид графика (отключить оси и т.п.), то получится следующее: Видео:
1cRT3LYYVtU
Решение 3 (уже не такое очевидное) - использование сторонних инструментов для визуализации.
В этом плане очень сложно сделать хороший выбор. Я выбрал среду машинного зрения HALCON от компании MVTec, просто потому что раньше пользовался ей и в ней есть поддержка .NET/ActiveX. Среда отнюдь не бесплатная, но она стоит своих денег. Используем в внешнюю процедуру visualize_object_model_3d, которую запускаем с помощью .NET узлов. Оставляя за кадром технические детали реализации, покажу сразу картинки: Видео:
ZTuQRJDP2L8
(Если кому-то станет интересно и он решит протестировать HALCON в триал-режиме или даже купить, то я выложу , использовавшийся для вызова процедуры.)
Теперь, собственно, мои замечания.
Решение 1.
1) Насколько я понимаю, инструмент Create Height Field строит классическую карту высот, т.е. набор точек (вертексов), соединённых между собой (аналог terrain в 3D-моделировании). Временами получается красиво, временами нет. Я не нашёл способа отключить этот "частокол", т.е. сделать так, чтобы отображались только точки, без соединяющих связей.
2) Плохо, что вручную нужно выставлять положение камеры. Признаю, долго подбирал такие координаты, чтобы меня устраивала исходная позиция объекта. И я не совсем уверен, что такие координаты подойдут для другого объекта. В принципе, можно рассчитывать каждый раз положение камеры по геометрическим параметрам объекта. Но это, опять же, лишняя работа. А магической опции "поместить в центр и отдалить камеру" нигде нет. :( Также совсем неочевидна связь параметра ModelView Matrix и исходного положения (Camera Position, Target, Up Direction). В сети есть , преобразующий ModelView Matrix, но в итоге реально получаем только один кластер - Camera Position. Как рассчитать другие два -
3) Не понятно, как окрасить модель в градиент. Одним цветом, к сожалению, плохо передаётся глубина объекта. А с градиентом становится и красиво, и информативно. Если только применить текстуру на объект, но её сначала нужно создать, либо загрузить из файла. Короче, опять лишняя работа.
4) Не совсем представляю, как исключить нулевые точки из построения. Слева/справа ещё можно обрезать. А что делать там, где находится полезная информация...
5) На LV 2014 64-bit как-то глючит: рисует артефакты по всему экрану, хотя должен рендерить сугубо в своё окошко. Надо проверить на 2015.
Решение 2.
Это решение понравилось даже больше, чем предыдущее. Однако осталась проблема 1, хотя на неё можно при желании забить. Проблема 2 решена - объект всегда помещён по центру, а камера отдалена так, как нужно. Проблема 3 решена - можем выбрать любой градиент, как душе угодно. Проблема 4 осталась, но теперь она менее выражена - мы можем окрасить нулевые точки цветом фона (чёрным, например) и тогда они будут почти не видны (иногда можно увидеть в некоторых позициях).
1) Вторая проблема решилась, но породила другую - объект всегда по центру, сдвинуть его мы не можем. При сдвиге он возвращается на своё место. Это мешает разглядывать детали.
2) При длительном использовании графика (открытие свойств, вращение/зуммирование объекта) может либо зависнуть, либо вылететь Правда, я это мало тестировал, надо будет на последних версиях проверить.
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-визуализации.