У многих команд до сих пор живут проекты времён Kinect и первых Astra: код на OpenNI2, обвязка в OpenCV, где-то ROS 1 с openni2_launch. Переписывать это под новый SDK ради замены железа жалко — и не нужно. У Orbbec есть OpenNI2-совместимый слой: вы ставите OpenNI2, подкладываете драйвер Orbbec в каталог драйверов, и весь существующий код продолжает открывать устройство через знакомые openni::Device и openni::VideoStream. В этом гайде пройдём путь целиком: установка, подключение драйвера Orbbec, проверка через NiViewer, чтение глубины из C++ и из OpenCV, и отдельный раздел про ROS 1. В качестве подопытной возьмём Astra 2 — камеру со структурированным светом, которая по формату данных полностью вписывается в привычный OpenNI-пайплайн.
Когда OpenNI2-шлюз — правильный выбор? Если проект работает, размечен тестами и его стоимость целиком в коде, а не в железе: замена камеры не должна превращаться в переписывание. Новый SDK (Orbbec SDK v2 с pyorbbecsdk) даёт больше возможностей — синхронизацию, современные форматы, официальную поддержку новых камер — и для новых проектов мы советуем именно его. Но для поддержания работающего парка устройств шлюз экономит недели: сессия миграции легко превращается в месяц регрессионного тестирования, а OpenNI-слой продолжает делать ровно то, ради чего вы его держали.
Что понадобится
- камера Orbbec (Astra 2 для indoor-сцен; логика та же для всей линейки Astra);
- Linux x64 (примеры для Ubuntu 20.04/22.04) или Windows;
- OpenNI2 (пакеты дистрибутива или SDK Orbbec с комплектным OpenNI2);
- драйвер Orbbec для OpenNI2 из комплекта Orbbec SDK;
- для ROS 1 — ROS Noetic и пакеты
openni2_camera,openni2_launch.
Пошаговая настройка
Шаг 1. Ставим OpenNI2
На Ubuntu достаточно пакетов дистрибутива:
sudo apt update
sudo apt install libopenni2-dev openni2-utils
NiViewer --help
Утилита NiViewer — ваш первый тест: если она видит камеру, значит шлейф OpenNI2 собран правильно. В Windows OpenNI2 проще взять из комплекта SDK Orbbec — там уже собраны и среда, и драйвер.
Шаг 2. Подкладываем драйвер Orbbec
OpenNI2 ищет плагины-драйверы в своём каталоге OpenNI2/Drivers. Из комплекта SDK Orbbec возьмите библиотеку OpenNI-драйвера и скопируйте её туда:
sudo mkdir -p /usr/lib/OpenNI2/Drivers
sudo cp libOrbbecDriver.so /usr/lib/OpenNI2/Drivers/
# имя файла и путь сверяйте с комплектом вашей версии SDK
NiViewer
Путь к системному каталогу драйверов может отличаться между сборками OpenNI2 — niReg -l покажет зарегистрированные модули, а OpenNI.ini в конфигурации OpenNI2 указывает, откуда читать драйверы. Если в комплекте SDK есть скрипт установки — используйте его, он прописывает и каталог, и udev-правила доступа. Наконец, скопируйте udev-правила из SDK в /etc/udev/rules.d/ и выполните sudo udevadm control --reload-rules, затем переподключите камеру — без прав доступа устройство увидит только root.
В Windows та же логика, но пути другие: каталог драйверов лежит рядом с OpenNI2.dll (например, OpenNI2/Drivers в папке приложения или System32 для системной установки — зависит от того, как ставилась среда). Главное правило — битность: 64-битное приложение грузит 64-битную библиотеку драйвера, и наоборот; загадочный «device not found» в Windows чаще всего именно про несовпадение разрядности. Если SDK поставляет свой экземпляр OpenNI2, используйте его целиком — среду и драйвер из одного комплекта.
Шаг 3. Читаем глубину из C++
Минимальный каркас почти не отличается от примеров десятилетней давности:
#include <OpenNI.h>
#include <cstdio>
int main() {
openni::OpenNI::initialize();
openni::Device device;
if (device.open(openni::ANY_DEVICE) != openni::STATUS_OK) {
printf("Device open failed: %s\n",
openni::OpenNI::getExtendedError());
return 1;
}
openni::VideoStream depth;
depth.create(device, openni::SENSOR_DEPTH);
depth.start();
openni::VideoFrameRef frame;
depth.readFrame(&frame);
const uint16_t* data =
static_cast<const uint16_t*>(frame.getData());
int w = frame.getWidth(), h = frame.getHeight();
// расстояния в миллиметрах, 0 — не измерено
uint16_t center = data[(h / 2) * w + (w / 2)];
printf("center depth: %u mm, %dx%d\n", center, w, h);
depth.stop();
depth.destroy();
device.close();
openni::OpenNI::shutdown();
return 0;
}
Компилируется одной строкой с флагом -lOpenNI2 и, если ставили из пакетов, с путём к заголовкам /usr/include/openni2. Сверьте сигнатуры с examples вашей версии SDK — API стабильный, но детали инициализации в некоторых сборках чуть отличаются.
Шаг 4. Открываем камеру из OpenCV
Если OpenCV собран с поддержкой OpenNI2, глубина и облако точек доступны прямо через VideoCapture — это самый короткий путь для legacy-скриптов на Python:
import cv2
import numpy as np
cap = cv2.VideoCapture(cv2.CAP_OPENNI2)
if not cap.isOpened():
raise RuntimeError("OpenNI2 device not found")
ok, depth = cap.read() # для OpenNI-захвата read возвращает несколько каналов
depth_map = cv2.convertScaleAbs(depth, alpha=0.05)
cv2.imshow("depth", depth_map)
cv2.waitKey(0)
cap.release()
У OpenNI-бэкенда OpenCV есть специальные индексы каналов: CAP_OPENNI_DEPTH_MAP, CAP_OPENNI_POINT_CLOUD_MAP, CAP_OPENNI_BGR_IMAGE — читайте их через cap.retrieve(). Поддержка OpenNI2 в системной сборке OpenCV есть в Ubuntu, но если ваш pip-пакет opencv-python устройство не видит — это ожидаемо: pip-сборка собрана без OpenNI, берите системный python3-opencv или собирайте OpenCV сами.
Если нужен не только depth, но и цвет, читайте оба канала через cap.retrieve() с разными индексами — OpenCV-обёртка OpenNI сама выравнивает глубину на цвет, когда это включено свойствами устройства. Проверяйте, что кадры относятся к одному моменту: для статичных сцен различие незаметно, а на движущихся людях рассинхрон уже виден. Для серьёзной работы с парами кадров OpenNI-слой — это всё-таки мост для совместимости; тонкое управление синхронизацией остаётся в компетенции новых SDK.
Шаг 5. ROS 1 через openni2_launch
Для проектов на Noetic ставим пакеты и запускаем:
sudo apt install ros-noetic-openni2-camera ros-noetic-openni2-launch
roslaunch openni2_launch openni2.launch
Драйвер openni2_camera открывает любое OpenNI2-устройство, включая Orbbec с подключённым драйвером, и публикует привычные /camera/depth/image_raw, /camera/rgb/image_raw и /camera/depth/points. Параметр depth_registration включит выравнивание глубины на цветной кадр. Рабочесть проверяйте в rqt_image_view — дальше ваш старый граф узлов зарабатывает без единой правки.
Разбор кода
Ключевой момент всей схемы — разделение ролей. OpenNI2 — это API и среда: он определяет, как запрашивать потоки и получать кадры. Драйвер Orbbec — плагин внутри этой среды: именно он общается с железом по USB и конвертирует сырые пакеты в кадры глубины. Поэтому «OpenNI2-проект» и «камера Orbbec» не конфликтуют: код остаётся на стабильном API, а поддержка конкретного железа живёт в подкладываемом драйвере. Отсюда же и стратегия переноса: сначала добейтесь, чтобы NiViewer показывал обе стороны сцены, и только потом запускайте своё приложение — так вы сразу локализуете, на каком уровне проблема.
Про единицы и форматы: глубина в OpenNI2 приходит в миллиметрах в 16-битном формате, и legacy-код, рассчитанный на Kinect-эпоху, обычно это уже предполагает. Если вы оборачиваете данные в OpenCV Mat или NumPy, не забудьте про stride: ширина строки может быть выровнена, и прямой reshape без учёта шага даст «съехавшую» диагональную картинку — классическая ошибка при первом запуске. Дырки данных (ноль) оставляйте нулями до поры: крашить их в минимум ради визуализации — верный способ потом не разобраться, где реальные стены, а где отсутствуют измерения.
Что изменится по сравнению со старыми камерами? В первую очередь — реальные разрешения и частоты: у современной линейки максимум глубины выше, а значит, ваш код, зашитый под конкретное 640x480, может потребовать перенастройки профилей через VideoMode. Формат данных при этом тот же: uint16 в миллиметрах, ноль — нет измерения. Вся арифметика («пиксель — луч», облако точек по интринсикам) продолжает работать без изменений. Если старый код полагался на особенности конкретного драйвера (порядок включения потоков, тайминги), перепроверьте эти места — здесь и помогает оговорка «сверьте с examples вашей версии SDK».
| Старый стек | Что делать | Объём правок |
|---|---|---|
| C++ на OpenNI2 | драйвер Orbbec в OpenNI2/Drivers, код не трогаем | только установка |
| OpenCV CAP_OPENNI | переключить на CAP_OPENNI2 | одна строка |
| ROS 1 openni2_launch | оставить как есть, проверить udev | конфигурация |
| NiViewer-скрипты диагностики | работают без изменений | нет |
Частые проблемы
«Device not found» или пустой список устройств
Три типовые причины. Первая — драйвер не в том каталоге: OpenNI2 читает путь из своего OpenNI.ini, и путь из инструкции в интернете может не совпасть с вашей сборкой; проверьте через niReg -l. Вторая — права доступа: без udev-правил устройство доступно только root, запустите sudo NiViewer для проверки гипотезы и затем поставьте правила из SDK. Третья — устройство занято: OpenNI2 не умеет делить камеру между процессами, закройте ROS-узел, NiViewer и всё, что могло открыть поток.
Глубина есть, цвет не открывается
Проверьте, что поток color создаётся отдельным VideoStream на SENSOR_COLOR и что выбранный VideoMode поддерживается камерой — попросите список режимов через device.getSensorInfo() и не хардкодьте экзотические разрешения. Для совмещения кадров включите регистрацию глубины на цвет (в OpenNI2 — соответствующий свойство устройства, в ROS-драйвере — параметр depth_registration); без неё маска глубины и цветной кадр смещены, потому что сняты с разных точек.
Камера видна, но кадры чёрные или шумные
Чёрная глубина при живом устройстве почти всегда означает, что запрошен режим, который железо в данных условиях не тянет, либо поток открылся с нулевыми метаданными. Запросите список доступных VideoMode через getSensorInfo и откройте заведомо поддерживаемый. Шумная «снежная» глубина у структурированного света — это засветка: яркое солнце или отражатели в кадре убивают паттерн проекции; проверьте сцену из NiViewer в тех же условиях. И не забывайте про прогрев: первые секунды после старта потока данные могут идти с пропусками — давайте камере секунду-две на стабилизацию до оценок качества.
Нестабильная частота кадров по USB
Структурированный свет и полный поток depth+color требуют USB 3.0. Убедитесь командой lsusb -t, что камера на линии 5000M, а не 480M; удлинители и хабы замените коротким кабелем. На ноутбуках с комбинированными портами помогает перенос камеры на другой контроллер — как найти «свой» контроллер, рассказано в нашем гайде про несколько камер на одном хосте.
Железо под legacy-проекты есть в каталоге Orbbec на luwam.ru. Для такого шлюза лучше всего подходят Astra 2 (структурированный свет, привычный OpenNI-профиль) и Gemini 335L, когда нужен запас по дистанции. Дадим консультацию по SDK и совместимости, выставим счёт для юрлица, гарантия 1 год.
Камеры Orbbec в наличии на LUWAM
- Orbbec Femto Bolt — iToF 4K, замена Azure Kinect — 99 900 ₽
- Orbbec Gemini 335L — стерео для роботов и SLAM — 99 900 ₽
- Orbbec Astra 2 — структурированный свет, сканирование помещений — 99 900 ₽
Весь каталог Orbbec · консультация по SDK · счёт для юрлица в день обращения · гарантия 1 год.

