Как спроецировать облако точек на камеру
Что проверяют
Знаете ли вы модель камеры-обскуры и разницу между внутренними и внешними параметрами. Типичные уточнения: что делать с точками за камерой, как учесть дисторсию и откуда берётся преобразование между лидаром и камерой.
Как отвечать
Проекция идёт в три шага:
- внешние параметры (extrinsics): переводят точку из системы лидара или мира в систему камеры:
X_cam = R @ X + t, гдеRматрица поворота 3×3, аtвектор сдвига. Вместе это[R|t]размером 3×4, берётся из калибровки лидар-камера; - отсечение: оставляем только точки с
Z_cam > 0. Точки за камерой после деления на глубину попадают в кадр зеркально; - внутренние параметры (intrinsics): матрица
Kс фокусными расстояниямиfx,fyв пикселях и главной точкойcx,cy. Пиксель считается какu = fx * X / Z + cx,v = fy * Y / Z + cy.
В одну строку: p = K @ [R|t] @ X_h, затем деление на третью компоненту. После этого отбрасываем пиксели за границами кадра.
На NumPy всё делается без цикла по точкам: облако как массив (N, 3), pts_cam = pts @ R.T + t, маска по глубине, затем uv = (pts_cam @ K.T)[:, :2] / pts_cam[:, 2:3]. Если у камеры заметная дисторсия, используйте cv2.projectPoints, который принимает rvec, tvec, K и коэффициенты дисторсии, или работайте с ректифицированным изображением. Когда в один пиксель попадают несколько точек, для карты глубины оставляйте ближайшую.
Проговорите соглашения об осях: у камеры в OpenCV Z смотрит вперёд, а Y вниз, у лидара обычно X вперёд и Z вверх. Путаница здесь даёт облако, повёрнутое на 90 градусов.
Где спотыкаются
Умножают матрицу K размером 3×3 на однородный вектор из четырёх компонент. Внешние параметры при этом пропущены, и код либо падает на размерностях, либо проецирует точки не из той системы координат.
Не фильтруют точки за камерой и с нулевой глубиной, получая мусор в кадре и деление на ноль.
Путают направление преобразования: калибровка отдала переход из камеры в лидар, а его применяют к точкам лидара без обращения матрицы.