Skip to content

RU Revopoint Tools

rkfsociety edited this page Oct 21, 2026 · 2 revisions

Инструменты Revopoint для Windows

Русский · English source

Назначение и статус

Инструменты командной строки напрямую работают с камерой через UVC и с двухосевым поворотным столом через Windows API. Они не используют платный SDK Revopoint; запускать Revo Scan во время захвата не требуется. Перед захватом установите локальную калибровку именно своего сканера по инструкции по калибровке. Файлы калибровки не входят в Git.

Захватывайте кадры при неподвижном столе и поворачивайте его между кадрами. Обычный режим — поворот шагом 30° при наклоне 0°. Пользователь установил предел наклона стола ±10°, хотя протокол допускает больший угол. Физический масштаб, калибровка осей и регистрация требуют проверки; облако точек или успешное совмещение сами по себе не подтверждают метрически точную модель.

Облако точек как референс CADYX

Готовый PLY только с точками можно загрузить в проект через staged-загрузку файлов скана Agent API/MCP, затем импортировать командой import_project_point_cloud с блокировкой проекта (file — имя загруженного PLY, name необязателен). Сохранённая сцена и PNG сервера отображают вершины как точки, без реконструкции поверхности и без приписывания физических единиц. Команда принимает от 3 до 300 000 конечных XYZ-точек без полигональных граней.

Для обратного проектирования по сечениям используйте import_project_scan/import_scan, чтобы создать треугольную сетку. Выравнивание скана и инструменты сечений не работают с референсом, содержащим только точки. См. контракт обратного проектирования и общий контракт viewport. Импорт в CADYX — отдельная операция проекта, а не команда управления столом и не автоматический этап каждого захвата.

Сборка

Запустите из корня репозитория в PowerShell:

.\tools\revopoint\build.ps1

Сборке нужны установленные Visual Studio C++ Build Tools, Windows SDK и компилятор C# из .NET Framework. Исполняемые файлы записываются в tools/revopoint/build/; Git игнорирует этот каталог.

Захват одного кадра глубины

Перед захватом закройте Revo Scan, чтобы программа не удерживала камеру глубины. Матрица Q должна принадлежать тому же сканеру. В Revo Scan 5 она находится по пути:

$qFile = Join-Path $PWD 'tools\revopoint\calibration\Q.bin' # локальный файл этого сканера; не отслеживается Git
$outPrefix = Join-Path $PWD 'projects\revopoint_probe\frame'
& .\tools\revopoint\build\CaptureY16.exe `
    --out-prefix $outPrefix `
    --q-file $qFile `
    --depth-scale 0.005

Рядом создаются frame.raw, frame.ply и frame.json; команда откажется перезаписывать любой из этих файлов. RAW содержит один кадр Y16 размером 640×400 в little-endian. При перепроецировании каждое значение uint16 интерпретируется как глубина (raw × depth_scale, мм); первые три строки локального Q.bin задают луч камеры, который затем масштабируется так, чтобы Z совпала с измеренной глубиной. Для PLY приняты предполагаемые миллиметры. Соответствие байтов прямого UVC-кадра буферу SDK пока предварительное. Локальный масштаб конкретного сканера и его статус читаются из tools/revopoint/calibration/depth_scale.json; перед захватом проверьте настройку калибровки.

Чтобы повторно перепроецировать сохранённый RAW после изменения обработки без подключения к камере, используйте reproject_y16.py. Каталог для результата должен существовать (обычно это папка того же проекта CADYX); существующие результаты не перезаписываются:

$calibration = Join-Path $PWD 'tools\revopoint\calibration'
$projectPath = Join-Path $PWD 'projects\<existing CADYX project folder>'
$scale = (Get-Content (Join-Path $calibration 'depth_scale.json') -Raw | ConvertFrom-Json).depth_scale_mm_per_raw_unit
python .\tools\revopoint\reproject_y16.py `
    --raw-file (Join-Path $projectPath 'frame.raw') `
    --q-file (Join-Path $calibration 'Q.bin') `
    --output-prefix (Join-Path $projectPath 'frame_reprojected') `
    --depth-scale $scale

Для измерения непрерывной частоты захвата добавьте --frames 120. Камера остаётся открытой на всю последовательность; утилита сохраняет упакованные кадры в frame_burst.raw, записывает метки Media Foundation, время потока и UTC-время получения в frame_timestamps.csv, а также выдаёт частоты по меткам и настенным часам. PLY остаётся превью первого кадра. Ранний опыт на 120 кадрах дал около 4,53 кадра/с по меткам; более позднее синхронное измерение обеих камер на полном обороте длилось свыше 40 секунд и заменяет этот результат для проверенной конфигурации.

& .\tools\revopoint\build\CaptureY16.exe --out-prefix $outPrefix --q-file $qFile --depth-scale 0.005 --frames 120

Кнопка проекта Сканер запускает непрерывный поток CaptureY16 --live-only и отображает откалиброванные 3D-точки в существующем canvas #model-preview; отдельные iframe и окно предпросмотра не используются. Основной viewer опрашивает read-only endpoint кадра, перепроецирует Y16 через Q.bin и сохраняет положение камеры во время обновлений. Ближайшая к пикселю (320, 200) точка первого кадра задаёт начало координат (0, 0, 0); центр вращения и радиус вписывания остаются постоянными при замене кадров.

В этом режиме в .revopoint-live.raw хранится только текущий кадр; отдельные RAW/PLY/метаданные для каждого скана и burst-файл не создаются, кэш кадра удаляется при остановке. Live-просмотр и захват 360° несовместимы, потому что используют одну камеру глубины. Облако точек загружает выбранный сохранённый PLY в тот же canvas. В отдельной диагностической странице кадр старше секунды считается остановленным. Масштаб глубины взят из журнала установленного SDK Revo Scan, однако соответствие прямому UVC-потоку и точность по известному размеру не проверены. Маршрут /scanner оставлен для диагностики.

Пример длительного захвата с вращением стола:

& .\tools\revopoint\build\CaptureY16.exe --out-prefix (Join-Path $projectPath 'capture') --q-file (Join-Path $calibration 'Q.bin') --depth-scale $scale --frames 1000 --fps 15 --live-raw (Join-Path $PWD 'projects\.revopoint-live.raw')

Чтобы включить только позиционное live-превью без сохранения RAW/PLY/метаданных каждого кадра или burst-файла, запустите:

$livePath = Join-Path $PWD 'projects\.revopoint-live.raw'
$stopPath = Join-Path $PWD 'projects\.revopoint-live-preview.stop'
& .\tools\revopoint\build\CaptureY16.exe --live-only --live-raw $livePath --stop-file $stopPath --fps 15

Страница сканера читает последний кадр из кэша фиксированного размера $livePath. Чтобы остановить просмотр из другого окна PowerShell, создайте файл-сигнал; захват завершится после следующего кадра:

New-Item -ItemType File -Path (Join-Path $PWD 'projects\.revopoint-live-preview.stop')

Непрерывный захват при движении поворотного стола

BLE-контроллер способен вращать стол, пока работает UVC-считыватель. В проверенном опыте наложили захват 90 кадров на поворот 30°: движение заняло 2,27 с, захват получил 90 кадров со скоростью 4,54 кадра/с по меткам Media Foundation, после чего стол вернули в 0°. Открытая панель браузера показывала около 3 кадров/с, то есть дополнительная нагрузка опроса и отрисовки заметна. Регистрация, проверка масштаба и объединение полного скана ещё не подтверждены.

Для записи угла с метками времени и поворотом в рамках одного сеанса используйте:

& .\tools\revopoint\build\TurntableController.exe monitor 24 (Join-Path $PWD 'projects\angles.csv') 3 30

Аргументы задают длительность наблюдения, CSV-путь, задержку перед относительным поворотом и его угол. Команда сохраняет одно BLE-соединение, записывает UTC-отсчёты поворота и наклона и отправляет команду движения по тому же соединению. В live-захвате на 120 кадров контроллер записал 88 отсчётов угла и наблюдал движение 0°→30°; после опыта стол вернули на 0°. Наклон проверен в поддерживаемом диапазоне: цель +30° дала +29,2°, цель −30° — −30,0°, команда обнуления вернула обе оси на 0°. +QR,TILTVALUE; считывает текущий наклон, а +QR,TILTANGLE; сообщает поддерживаемый диапазон.

UTC-метки кадров и отсчёты угла можно объединить линейной интерполяцией. В проверенном синхронном запуске всем 120 кадрам сопоставлена интерполированная поза стола в диапазоне 0°–30°; строки по кадрам сохранены в capture_frame_poses.csv. В CSV наблюдения записан также наклон из +QR,TILTVALUE;. Эти данные могут задавать жёсткие позы отдельных кадров, если оси и центр стола откалиброваны. Прямое преобразование глубины UVC и механические оси ещё не проверены, поэтому таблица поз не подтверждает точность итоговой модели.

Неподвижные позы маркеров

Для исследования маркеров и камеры этот сценарий снимает каждый угол при неподвижном столе. Процессы DepthCam и RGBCam завершаются до следующего поворота на 30°:

$projectPath = Join-Path $PWD 'projects\Исходные кадры сканирования'
.\tools\revopoint\capture_marker_sweep.ps1 -ProjectPath $projectPath -OutputFolderName marker_poses -FramesPerPose 1 -Fps 15

Сценарий снимает по одному или несколько кадров каждой камерой при 0°, 30° … 330°, а после завершения последнего процесса камеры поворачивает стол только по оси вращения на 30° обратно к нулю. Наклон не задаётся. Поза и время захвата записываются в poses.csv и capture_manifest.json; исходные кадры, превью облака и RGB-изображения хранятся в отдельном каталоге запуска внутри существующего проекта CADYX. TurntableController отклоняет команды rotate, sweep, capture-sweep, tilt и zero, пока активны известные процессы сканера. Частичный результат сохраняется, при ошибке автоматическое движение стола не выполняется.

Приведённый ниже analyze_marker_sweep.py предназначен для старых захватов с движущейся камерой, непрерывными временными потоками и turntable_sweep.csv. Он не обрабатывает формат неподвижных поз; эти захваты сопоставляются с записанными углами поз.

Для старого непрерывного прохода использовалась команда:

py .\tools\revopoint\analyze_marker_sweep.py .\projects\revopoint_marker_sweep_YYYYMMDD_HHMMSS

Анализатор запускает включённый DetectMarkers.exe для RGB-кадров без готового CSV кандидатов, затем записывает рядом с захватом frame_pose_sync.csv, marker_detections.csv, marker_tracks.csv, marker_trajectories.csv и sweep_analysis.json. По умолчанию RGB и Y16 связываются по UTC-времени получения с допуском 45 мс; угол стола интерполируется между телеметрическими отсчётами. Дополнительный проход по траекториям отбирает компоненты столешницы по площади, жадно связывает близкие детекции и аппроксимирует их траектории синусоидой первого порядка по углу стола. marker_trajectories.csv по умолчанию помечает как вращающиеся кандидаты пути минимум с 10 наблюдениями, охватом угла 45°, размером в изображении 8 px и RMS аппроксимации не выше 25 px. Пороговые компоненты и траектории — исследовательские результаты, а сами по себе не доказывают идентичность отражателей. Анализатор не перезаписывает файлы; для отдельного повторного прохода задайте --suffix _2.

Для сравнения полнооборотных траекторий с экспортированной картой из 34 точек без предположения об абсолютной ориентации скана запустите:

py .\tools\revopoint\register_marker_map.py .\projects\revopoint_marker_sweep_YYYYMMDD_HHMMSS --map .\framesmall_points.csv

Утилита на стандартной библиотеке проецирует карту и коэффициенты синусоидальных траекторий в 2D, предлагает соответствия длинных траекторий с помощью RANSAC без привязки к ориентации, масштабу и переносу, уточняет преобразование наборов точек, затем оценивает оставшиеся плавные треки, не меняя найденное преобразование. Для опорных соответствий выдаются leave-one-out ошибки и поле fit_anchor. Рядом с захватом создаются marker_map_registration.csv и .json; существующие файлы не перезаписываются, для сохранения предыдущего результата задайте --suffix _2. Все строки имеют статус candidate: детекции получены жадным трекингом, физические единицы карты неизвестны, а внутренняя перекрёстная проверка не подтверждает независимо личности маркеров и не масштабирует/объединяет скан объекта.

Контрольный проход пустого стола от 2026-10-16: при запросе 10 fps за примерно 43,4 с получено 570 кадров Y16 и 567 RGB. По Media Foundation оба потока выдавали 13,12 fps. Стол прошёл 359,9° за 32,0 с; в интервал движения попало по 420 кадров каждого потока, все RGB-кадры сопоставились с Y16 в пределах 45 мс. Всего за захвату этому допуску соответствовали 567 пар RGB/Y16; 95-й процентиль абсолютного смещения времени — 22,4 мс. Камеры получили UTC-метки по часам получения, а не по общим аппаратным часам. Телеметрия стола содержала 73 отсчёта угла/наклона с медианным интервалом 410 мс, поэтому позы между ними интерполированы. Стол остановился на −0,2°, наклон нулевой. Отдельный burst на 60 кадров также дал около 13 fps, но закончился до вращения и не считается захватом во время движения.

Повторный проход с поднятым сканером позже в тот же день получил 572 кадра Y16 и 568 RGB за 43,56 с: скорости получения составили 13,108 и 13,105 fps. В окне движения длительностью 32,12 с пришло 422 Y16 и 421 RGB; все 421 движущихся RGB-кадра сопоставились с Y16 в пределах 45 мс. Угол охватил 359,9°, стол вернулся к −0,3°, наклон 0°. При пороге 150 область столешницы содержала в среднем 15,9 RGB-кандидата на движущийся кадр; анализ траекторий оставил 29 плавных вращающихся кандидатов. Попытка сопоставлять точечный рисунок каждого кадра дала лишь 4–7 взаимно-однозначных пар (медиана 6 при 9–13 детекциях), а оценённые повороты не следовали телеметрии стола (корреляция −0,074). Совокупный прототип регистрации траекторий нашёл 9 опорных соответствий из 10 длинных треков, затем оценил ещё один короткий трек при пороге 35 px. RMS опорной подгонки составил 7,985 px, leave-one-out RMS — 14,074 px; дополнительное соответствие не проходило leave-one-out проверку. Это кандидаты, а не независимо подтверждённые личности. В кадре нет краёв столешницы, поэтому одновременно видна лишь часть отражателей.

Этот запуск демонстрирует более 10 fps для обоих прямых UVC-потоков за полный оборот стола на данной установке. Он не проверяет масштаб глубины в метрических единицах, точное соответствие 2D-маркеров карте MKF, калибровку осей камеры и стола или полноту сетки объекта. Короткие ранние тесты режимов на том же ПК показывали заметно меньшую скорость; проверяйте производительность в каждой конфигурации захвата.

В раннем проходе 2026-10-16 стандартная оценка траекторий нашла 32 плавных вращающихся кандидата; разрешение разрыва ассоциации в 10 кадров дало 31, а минимальная площадь компонента 200 px — 30. Числа близки к 34 точкам MKF, но не доказывают, что это те же отражатели. Для повторного прохода с поднятым сканером получены описанные выше кандидаты соответствий; восстановление полного набора отражателей и независимая проверка маркеров остаются открытыми.

Поле зрения сканера охватывает только часть поворотного стола. В том же проходе пустого стола первый кадр Y16 640×400 содержал 1 259 ненулевых пикселей; поиск связных областей с порогом 1 обнаружил пять областей при стандартных ограничениях размера. Поэтому одного кадра недостаточно для карты из 34 отражателей. Карту нужно накапливать по всему вращению, связывая каждое наблюдение с измеренным углом; точное соответствие точкам MKF ещё предстоит установить.

Экспериментальное объединение 360°

Двенадцать RAW-кадров с шагом 30° перепроецировали и проверили поворотом вокруг Z с оценкой смещения по перекрытию. Для экспериментального преобразования −30° на каждый заданный шаг +30° и центра примерно [28.8, -5.4] в текущих Q-координатах получилось 81–94% перекрытия соседних пар по ближайшим соседям в пределах 5 координатных единиц. Центр и знак оценены эмпирически, это не механическая калибровка. Дедуплицированные по вокселям PLY и JSON-описание происхождения сохранены рядом с исходными кадрами как approx_fused_candidate.ply и approx_fused_candidate.json.

Для новой папки scan_360.ps1 диагностическое объединение без внешних Python-пакетов выполняет fuse_turntable_scan.py:

python .\tools\revopoint\fuse_turntable_scan.py .\projects\revopoint_model_scan

Скрипт читает измеренный угол каждого кадра, оценивает XY-центр при предположении, что ось Z камеры совпадает с осью стола, оценивает соседние пары с чётными индексами и проверяет нечётные пары на отложенных данных, возвращает все облака к первой позе и удаляет дубли по вокселям. Он записывает экспериментальные PLY и JSON рядом с исходными данными и не перезаписывает результаты. По умолчанию для оценки центра используется каждая 64-я точка, радиус поиска — 20 единиц вокруг медианного центра облака, шаг грубого поиска — 4 единицы с последующим локальным уточнением. Если предполагаемый центр дальше от середины облака, увеличьте радиус. Для изменения выборки/поиска используйте --match-stride и параметры поиска центра.

Перекрытие — диагностический показатель, а не гарантия точности: преобразование независимо не откалибровано, физический масштаб Q-координат не подтверждён, скрытые поверхности остаются отсутствующими. В захвате текущей установки от 2026-10-16 плотные настройки оценили центр [32.1, -22.7, 0] и дали перекрытие точек 82,2% на обучающих парах и 86,9% на отложенных парах в пределах 5 Q-единиц. Ранее разреженные настройки дали 71,1% на отложенных данных, ручная оценка — около 90% при другой выборке. Это диагностические варианты; multi-tilt опыт добавил точки, но лишь немного увеличил покрытие относительно прежнего скана пользователя. Преобразование, масштаб и полноту нужно валидировать.

Первичная реконструкция CADYX содержала 24 641 вершину и 49 979 треугольников. Последующие попытки с большим числом треугольников и фильтрацией плотности/выбросов всё равно дают тонкий пластинчатый результат с отдельными фрагментами. Это диагностическая модель, а не проверенный полный скан. До принятия результата нужно проверить прежнюю трактовку raw/256, механическую ось/центр и покрытие закрытых поверхностей.

У сетки и исходного объединённого облака сходны собственные значения PCA для наименьшего измерения (14,1 против 15,6 единицы координат²). Значит, тонкая пластинчатая форма уже присутствует во входном объединённом облаке, а не появляется только при реконструкции Пуассона. Это всё равно не доказывает полноту покрытия самого объекта: нижняя и закрытые поверхности не проверены.

Объединение двух кадров с известной позой стола

Если измерен угол стола и есть оценка оси/центра, объединить два сохранённых PLY только с точками вокруг произвольной 3D-оси можно так:

$run = Join-Path $PWD 'projects\revopoint_single_frame_20261019'
python .\tools\revopoint\fuse_known_pose_pair.py `
    (Join-Path $run 'depthcam_0deg_001.ply') `
    (Join-Path $run 'depthcam_15deg_001.ply') `
    (Join-Path $run 'fused_pair_0_15deg.ply') `
    --table-angle-deg 15 `
    --axis -0.001874 -0.154783 0.987947 `
    --pivot 34.941 -19.133 117.392

Утилита поворачивает второй кадр на отрицательный измеренный угол стола, сообщает выборочное двунаправленное перекрытие при 1/2/5 Q-единицах, усредняет объединённые точки по вокселям и пишет JSON-происхождение рядом с PLY. Она не перезаписывает ни источник, ни существующий результат. Передавайте независимо измеренный угол и обоснованные ось/центр. В приведённом опыте повторно использованы ось и центр из прежней регистрации по маркерам, поэтому совмещение предварительное. Физический масштаб не подтверждён, результат охватывает только поверхности, видимые в двух кадрах.

Доступные режимы камеры и дополнительные измерения

Список объявленных камерой режимов:

& .\tools\revopoint\build\CaptureY16.exe --list-modes

Подключённая камера объявляет Y16 640×400, 1280×800 и 640×800 с номинальными режимами 5, 10 и 15 fps. Ранние явные тесты 640×400 на номинальных 5/10/15 fps дали около 4,6 fps по временным меткам Media Foundation в опытах по 40 кадров. Позднее результаты разошлись; см. ниже. Прямой UVC-путь не показал стабильно 10 fps; эти тесты не измеряют весь конвейер Revo Scan.

Windows также перечисляет интерфейс RGBCam с MJPG и NV12 1280×800, номинально 10/15/20/30 fps. CaptureRgb.exe умеет напрямую запрашивать любой из объявленных форматов. 2026-10-16 оба формата по отдельности при запросе 10 fps не выдали кадр за 12-секундный watchdog. Если сначала запустить считыватель DepthCam, удалось получить одновременно 30 RGB и 30 Y16 кадров при подключённой телеметрии стола. Метки Media Foundation охватили 15,65 с для RGB (около 1,9 fps) и 15,54 с для Y16 (около 1,9 fps); между первой и последней UTC-метками получения прошло 16,44 с (около 1,8 fps) и 21,1 с для процесса захвата (около 1,4 fps). Запрос 10 или 30 fps не поднял фактическую частоту до 10. Сопоставляйте потоки по UTC-времени получения: у RGB и глубины нет общих часов Media Foundation. JPEG-образцы могут содержать байты после EOI; утилита обрезает данные по конечному маркеру JPEG и сохраняет некорректный образец как .invalid-mjpg.bin до сообщения об ошибке. Журналы и кадры сохранены в projects/revopoint_marker_rotation_sync_20261016/.

Локальные DetectMarkers.exe и detect_y16_markers.py — начальные средства поиска ярких компонент, а не подтверждённая копия детектора Revopoint. Они выдают центры по яркости/серому или связным областям и измерения формы для осмотра. Экспорт пользователя framesmall.mkf содержит 34 записи с 3D-координатами и единичными нормалями; parse_mkf.py разбирает наблюдаемую структуру из 16-байтного заголовка и записей по 64 байта, экспортирует CSV/PLY. Бинарная раскладка проверена эмпирически по числу записей, конечности координат/нормалей и планарной согласованности, но смысл полей и единицы координат не документированы. Экспорт пригоден как референс для калибровки карты камера—стол, однако текущие 2D-детекции ещё не сопоставлены со всеми 34 записями и не проверены на точность.

Когда стол поворачивается между RGB-кадрами, для двух CSV детектора и измеренных углов используйте classify_marker_motion.py. Кандидаты, оставшиеся в том же центре пикселя, помечаются как неподвижные в изображении; без соседнего центра после поворота — как переместившиеся или не обнаруженные повторно. Это только средство отсева фона: оно не устанавливает, что перед камерой один физический отражатель, а маркер около оси может выглядеть неподвижным или неоднозначным. На сохранённой последовательности пустого стола −360°→−330° при пороге 150 по полному кадру найдено 33 и 32 кандидата до/после; классификатор выделил 5 неподвижных на изображении, 26 перемещённых/не найденных повторно и 2 неоднозначных. Четыре стабильных кандидата находятся выше видимого края стола, один расположен на столешнице и может быть около оси либо быть ложным. Обрезка до y >= 250 px оставляет 29 и 28 кандидатов. RGB-последовательность показывает полезное движение стола, но не подтверждает точную карту из 34 точек. Пример:

py .\tools\revopoint\classify_marker_motion.py `
  --before .\projects\capture\before_candidates.csv --before-angle 0 `
  --after .\projects\capture\after_candidates.csv --after-angle 30 `
  --min-y-px 250 `
  --out-csv .\projects\capture\motion_candidates.csv

Анализ DLL Revo Scan и изолированная проверка SDK

Пакет установленного Revo Scan 5.5.5 исследовали без запуска приложения. Подписанные DLL поставщика имеют действительные подписи Revopoint Authenticode; заголовков, import library и PDB в каталоге установки нет. В открытом репозитории Revopoint 3DViewer есть заголовки 3DCamera, import library и SDK DLL версии 3.2.23.0; enum CameraType явно содержит CAMERA_MINI_NORMAL и CAMERA_MINI_NO_RGB. SDK DLL экспортирует все 114 имён, присутствующих в установленной Revo Scan 3DCamera.dll версии 3.2.140.0; в установленной копии добавлены setSdkConfigData, setSdkConfigPath, getMarkersInfo и upgradeCameraPro. Изолированный вспомогательный процесс загрузил установленную DLL и перечислил подключённый MINI через публичную import library версии 3.2.23. ICamera::connect вернул код 8 (ERROR_NOT_SUPPORT): эта пара версий не позволила запрашивать калибровку во время работы и не является проверенным ABI интеграции. Публичный SDK не содержит заголовков или import library отдельной zxPointCloudProcessing64.dll Revo Scan.

3DCamera.dll экспортирует API камеры/кадров: перечисление, подключение/отключение, создание/запуск/остановку потоков, чтение одиночных и парных кадров, данных/формата/размеров/меток времени/дополнительных сведений кадра, запрос внутренних и внешних параметров/дисторсии и запрос информации о маркерах. Публичные заголовки описывают получение через callback и pull и требуют освобождать кадры после использования. Обобщённая структура ExtraInfo содержит необязательное расширение gyroPosAndPos с кватернионом q0..q3, гироскопом gx/gy/gz, ускорением, магнитным полем и оценкой движения. Это доказывает только то, что формат SDK может хранить такую метаинформацию, но не наличие её у исходного MINI. Пример 3DViewer превращает каждый входящий кадр глубины в облако с калибровкой камеры и публикует как live-обновление 3D; в этом пути нет многокадровой регистрации или слияния.

Журналы установленного Revo Scan для этой камеры указывают поток глубины 640×400, 15 fps (format:3) и depthScale=0.005. Хэш локального Q.bin совпадает с активным %LOCALAPPDATA%\RevoScan5\cameraparam\Q.bin; Pl.bin также совпадает побайтно. Файл Pl.bin размером 40 байт описывает 640×400 с fx=fy=891.2453, cx=52.7665, cy=199.49365; для Prgb.bin указаны fx=fy=899.3882, cx=331.0519, cy=202.1866. Перепроецирование умножает uint16 на записанный масштаб глубины, использует Q для луча, затем масштабирует луч до измеренного Z. Пара положений стола 0°/14,4° дала оценённый поворот облака 13,1° и направленное перекрытие 100%/97,9% в пределах 5 мм; прежняя трактовка disparity raw/256 давала лишь 2,7–3,1 Q-единиц устойчивого разброса глубины и оценённый поворот 0,7°. Это сильное внутреннее свидетельство в пользу исправленного метода, но не независимое доказательство тождественности UVC/SDK-буферов или абсолютного масштаба. Перед сертификацией масштаба проверьте известный размер.

Конвейер маркеров разделён на markerDetectionByGradient.dll и markerDetectionByJH.dll (фабрики IMarkerExtraction на OpenCV), markerMatchByEpipolar.dll (настройка камеры и неискажённые координаты точек), markerAlignByTriangle.dll (фабрика IMarkerAlign) и markerFusionByTriangle.dll (фабрика IMarkerFusion, импортирующая aligner). В fusion DLL найдены строки createBaFusion, выбор/оптимизация keyframe, совмещение frame-маркеров, глобальная оптимизация, фильтрация точек и промежуточные PLY. Это подсказки об архитектуре, а не восстановленный алгоритм и не гарантия того, что режим маркеров применяется к отражателям поворотного стола.

zxPointCloudProcessing64.dll экспортирует C++-классы и методы AlignPointCloud, AlignByMark, RobustRegisterDepthSeqs, GlobalRegisterDepthSeqs, RobustGlobalRegisterDepthSeqs, GlobalFuseDepthSeqs, ICPRegistration и IntegratePointCloudByFusion. Сигнатуры, восстановленные декоратором имён MSVC, включают RobustRegisterDepthSeqs::Init(Vector3 const&, double, double, bool, double, bool, int, int, int, double, bool), AddDepthFrame(IGridPointCloud*, DepthParm const*), StartSeqs(), GetPreview(), GetRegFrameInfo(int, Matrix4x4*, int*) и Finish(). Среди setters — оценка начального преобразования, robust ICP, минимально приемлемое перекрытие для трекинга, оптимизация фрагментов и групп. GlobalFuseDepthSeqs::Init(int, int, double, double, double, MergeType, int, bool, double) принимает кадры через AddDepthFrame(IPointCloud*, vector<Vector3> const*, Matrix4x4 const*, int), затем предоставляет FuseSeqs() и GetFusedCloud(bool). Это подтверждает наличие инкрементального пути регистрации/превью и отдельного глобального слияния. Единицы/значения по умолчанию параметров и контракт размещения/владения частных классов облаков GPP и DepthParm неизвестны; без этих данных прямой вызов из CADYX небезопасен. rpmarker.dll экспортирует SetImage, SetParam и Detect класса C++-детектора.

Пользователь подтвердил, что устройство — первая модель Revopoint MINI. В характеристиках MINI Revopoint указывает позиционные датчики: No. Не выводите наличие гироскопа из общих полей расширения SDK: текущий прямой UVC-захват считывает только RGB/Y16. Для захвата поворотного стола в CADYX используйте энкодер стола и откалиброванную визуальную/3D-регистрацию. JSON шагов калибровки MINI содержит параметры экспозиции для поз и границы левого/правого изображения. Круговые поля config/calibration/0A8/calibration.json принадлежат формату кодированной калибровочной мишени и не подтверждают диаметр отражателей стола.

CameraControls.exe читает стандартные диапазоны и текущие значения экспозиции/управления изображением DirectShow для перечисленных камер сканера. Утилита намеренно доступна только для чтения: в раннем опыте драйвер не подтвердил запрошенный ручной режим экспозиции RGB.

Для измерения временных меток других нативных режимов без применения к ним калибровки 640×400 задайте размеры и --measure-only:

& .\tools\revopoint\build\CaptureY16.exe --out-prefix (Join-Path $PWD 'projects\revopoint_rate\1280x800') --frames 40 --fps 10 --width 1280 --height 800 --measure-only

Дополнительные прямые UVC-измерения 2026-10-16 заметно различались между запусками. При 640×400 выбор номинала 5/10/15 fps дал по меткам Media Foundation 1,72–2,01 fps и по настенным часам 1,00–1,51 fps в тестах на 10–20 кадров; метки кадров приходили парами с интервалом около секунды. Более поздний синхронный проход длиной 43 с показал около 13,1 fps для обеих камер, включая 32-секундное вращение. У успешно полученных кадров Source Reader flags были нулевыми; чтение без кадра вернуло 0x100 (MF_SOURCE_READERF_STREAMTICK). CSV временных меток содержит флаги доставленных кадров, а консоль выводит флаги чтения без кадра. При 1280×800 запросы 15 и 10 fps оба дали 0,69 fps по меткам Media Foundation на 40 кадрах. При 640×800 и номинале 10 fps за примерно 150 с не удалось получить 40 кадров, запуск остановили. Считайте этот режим непроверенным, а не режимом с нулевой частотой. RAW-burst и CSV сохранены в projects/revopoint_mode_rate_20261016/.

Локальный журнал Revo Scan 5 для того же ID камеры даёт историческое сравнение: сопряжённый поток выдавал 12,3–13,0 fps в четырёх последовательных показаниях с 09:09:01 до 09:09:32 2026-10-14, затем около трёх минут — 5,7–6,7 fps; в 09:11:20 произошёл один сбой парного кадра (ошибка 7). Позже около 09:41–09:42 шесть подряд показаний давали 8,0 fps без сбоя пары в течение этой минуты. Счётчики RGB и глубины иногда расходились (глубина около 12 fps, RGB и парный поток около 6), поэтому важна парная скорость. Эти показания не подтверждают стабильные 10 fps. Более поздний независимый прямой UVC-проход показал свыше 10 fps при контролируемом вращении. В некоторых отрезках исторического журнала проприетарный конвейер был быстрее; колебания прямого считывателя не объяснены.

Масштаб преобразования RAW в disparity 256 предварительный и не сверялся с известным размером; считайте масштаб PLY неподтверждённым. Непрерывный проход записывает позы стола для каждого кадра и исследовательские 2D-треки ярких компонент, но не регистрирует/не объединяет 3D-кадры и не создаёт герметичную сетку объекта. 34 детекции не сопоставлены с 3D-картой framesmall.mkf и не проверены на точность. Пользователь подтвердил модель первой MINI; общие имена USB-камер не подтверждают IMU и не дают телеметрию позы.

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

Запрос состояния и управление двухосевым столом

Команда query считывает угол поворота и наклон. speed задаёт период оборота от 18 до 90 секунд (меньшее значение — быстрее). rotate отправляет один относительный поворот не более 30°; отрицательный угол меняет направление. tilt управляет только второй осью в пользовательском безопасном диапазоне −10°…+10° и сверяет текущее значение. Хотя протокол стола допускает большие углы, на этой установке не превышайте предел: около 29° деталь упала со стола. CLI соблюдает ±10°; zero возвращает обе оси в начальные положения. Наклоняйте только закреплённую деталь. stop отправляет останов обеим осям.

Утилита ищет BLE-сервис FFE1, подключается без сопряжения, проверяет GATT-имя REVO_DUAL_AXIS_TABLE и использует сервис FFE0/FFE1. Наблюдаемые ASCII-команды совпадают с независимо описанным протоколом Revopoint Dual-axis Turntable. Revo Scan, Revo Assistant или другой Bluetooth-клиент могут удерживать соединение стола. После потери ответа контроллер не повторяет команду движения.

& .\tools\revopoint\build\TurntableController.exe query
& .\tools\revopoint\build\TurntableController.exe zero
& .\tools\revopoint\build\TurntableController.exe speed 18
& .\tools\revopoint\build\TurntableController.exe rotate 5
& .\tools\revopoint\build\TurntableController.exe stop

Полный оборот с шагом 30°

Закрепите предмет на столе, оставьте сканер неподвижным, закройте Revo Scan и запустите захват в существующем проекте CADYX:

$projectPath = Join-Path $PWD 'projects\revopoint_model_scan'
.\tools\revopoint\scan_360.ps1 -ProjectPath 'projects\<existing CADYX project folder>' -DepthScale 0.005

Сценарий не создаёт новый проект. Кнопка Сканировать 360° захватывает 12 неподвижных поз через 30° и проверяет возврат стола в начальный угол. Стол должен быть заранее выровнен; сценарий не отправляет команду наклона или обнуления. CaptureY16 снимает один кадр и завершается, затем контроллер ждёт 3 с перед следующим движением для завершения обработки. Превью показывает последний сохранённый кадр, а не слияние движущегося видео. В проекте сохраняются RAW-кадры, предварительные PLY, копии калибровки, журнал поз и manifest. Масштаб прямого UVC-потока остаётся предварительным.

Кнопки Облако точек и Сетка расположены рядом со Сканировать 360° и используют существующий canvas #model-preview; iframe и отдельное окно не создаются. Облако заменяет отображаемую геометрию в общей сцене, где её можно вращать и масштабировать. Система координат стола задаётся первым кадром: устойчивое построение плоскости переводит столешницу и маркеры в XY, а её нормаль — в Z. Откалиброванный центральный луч изображения задаёт исходное начало координат в плоскости. После проекции в систему стола применяется одобренная пользователем ручная поправка центра X=+10 мм и Y=+48 мм; Z и ориентация плоскости не меняются. Пользователь визуально принял эту примерную поправку для данной установки по видам спереди и сбоку; это не калибровка по карте маркеров.

Каждый live-кадр Y16 перепроецируется в координатах сканера и обновляется без дополнительного поворота по энкодеру: физическое вращение уже отражено в последовательных кадрах камеры. Длина осей координат уменьшена втрое. Вид Сетка отображает текущую сетку viewport проекта в том же canvas; сам сетку не создаёт. Он выключен, пока облако явно не помечено готовым через scan_mesh_ready=1; предварительно объединённое облако не считается готовым. Результат остаётся треугольной сеткой, а не B-rep, и масштаб захвата не подтверждён.

Если все 12 кадров сохранены, но создание manifest завершилось ошибкой, восстановите только эти метаданные из журнала поз, не запуская сканер или стол:

.\tools\revopoint\scan_360.ps1 -ProjectPath 'projects\<existing CADYX project folder>' -ManifestOnly -RunId revopoint_<UTC run id>

Режим проверяет файлы захвата, нулевой наклон и телеметрию возврата к исходному углу, затем создаёт manifest.

Геометрическая регистрация полного оборота

Необязательная автономная утилита не использует энкодер стола, его ось или предполагаемый центр при совмещении облаков. Она вычисляет FPFH-дескрипторы, инициализирует каждую геометрическую пару через RANSAC, уточняет совмещение устойчивым point-to-plane ICP, затем оптимизирует ограничения соседних кадров и замыкания с первым кадром в графе поз Open3D. Облака прореживаются, остаётся крупнейшая связная компонента. Результат — PLY только с точками; сетка не строится. Документация Open3D: глобальная регистрация признаков и многокадровая регистрация.

Используйте отдельное виртуальное окружение, чтобы не смешивать его со средой приложения:

python -m venv .runtime\scan-reconstruction\venv
& .\.runtime\scan-reconstruction\venv\Scripts\python.exe -m pip install -r tools\revopoint\requirements-point-registration.txt
$runId = 'revopoint_<YYYYMMDDTHHMMSSZ>'
$project = 'projects\<existing CADYX project folder>'
$output = ".runtime\scan-reconstruction\${runId}_first_frame_geometric_candidate.ply"
& .\.runtime\scan-reconstruction\venv\Scripts\python.exe `
    tools\revopoint\register_point_clouds_first_frame.py $project $runId $output

Перед публикацией кандидата проверьте JSON sidecar: долю прямого перекрытия соседних пар, перекрытие последней и первой поз, долю крупнейшей компоненты, границы и остаточную локальную коррекцию. Если показатели расходятся или слабы, оставьте статус предварительным. Физический масштаб не подтверждён, пока его не сверили с известной длиной. Сценарий подготовки записывает результат вне проекта CADYX и не перезаписывает файлы; после проверки загрузите PLY в этот проект через cadyx_upload_project_scan по Agent API. Все исходные кадры захвата сохраняйте.

Multi-tilt захват и состояние регистрации

Сценарий multi-tilt выполняет пять полных оборотов в порядке 0°, +5°, −5°, +10°, −10°. Каждый оборот включает неподвижные позы через 30°, всего 60 кадров Y16, предварительные PLY-представления, метаданные и журналы поз проходов в выбранном проекте. Перед наклоном закрепите предмет; диапазон ограничен ±10°. Сценарий проверяет телеметрию наклона/вращения, сохраняет завершённые кадры при ошибке, возобновляет запуск по UTC Run ID и в конце возвращает обе оси домой. Он не создаёт второй проект и не перезаписывает существующие файлы запуска.

$runId = [DateTime]::UtcNow.ToString('yyyyMMddTHHmmssZ')
$projectPath = Join-Path $PWD 'projects\Исходные кадры сканирования'
.\tools\revopoint\scan_tilt_series.ps1 -ProjectPath $projectPath -RunId $runId

Регистрация — отдельный этап; нельзя считать, что ось стола совпадает с Z камеры. Ось наклона не откалибрована в координатах камеры. Предыдущий опыт fuse_multi_tilt_scan.py использовал XY-центр и предположение об оси Z для всех проходов; он создал плоское ошибочное облако и удалён. Проверка ICP первой соседней пары сошлась на 4,8° при заданном движении 30°, то есть нашла локальное плоское совмещение, а не надёжную позу. Не импортируйте этот кандидат как геометрию скана. PLY/JSON оставлены в проекте как неудачные диагностические данные; некорректное тело CADYX удалено, исходное тело для сравнения и все кадры захвата сохранены.

Кампания 20261016T135207Z от 2026-10-16 сохранила все 60 поз и вернула стол к нулю. Направленное совмещение старого кандидата покрыло около 45% всех точек референса в пределах 5 предварительных Q-единиц. Это говорит лишь о частичном покрытии: референс собран из видов нескольких сторон, а кадры могли не охватить всю его поверхность. Для пригодного результата нужна регистрация 3D-поз с независимо проверенными перекрытием и замыканием, прежде чем показывать объединённое облако как модель.

Clone this wiki locally