Карта несоответствия с облаком точек отключена

Я пытаюсь выполнить 3D-реконструкцию лица из двух изображений с помощью Python и OpecCV. Мне удалось выполнить калибровку камеры с помощью intructions здесь ссылку, а затем применяяcv2.stereoCalibrate() а также cv2.stereoRectify(). Впоследствииcv2.StereoSGBM использовался для вычисления карты диспаратности, и, наконец, cv2.reprojectImageTo3Dдля создания облака точек. Последний отображался с помощьюopen3dбиблиотека. Однако результатStereoSGBM.compute() очень шумно, и получившееся облако точек выглядит совсем не так, как должно.

Что я пробовал:

  • нормализация карты диспаратности: алгоритм выводит двумерный массив со значениями от -16 до 240, поэтому я установил его между 0 и 255 и 0,0 и 1,0 соответственно. Первый вариант пошел лучше
  • деление значений на 16 (как я видел в реализации на C++)
  • настройка параметров StereoSGBM. Я даже создал графический интерфейс для настройки параметров, но результаты все еще не были удовлетворительными.
  • используя StereoBM, однако особой разницы не было
  • используя разные тестовые изображения
  • использование изображений в оттенках серого
  • нормализация их в диапазоне 0,0 -> 1,0
  • обрезка неискаженных изображений
  • повторная реализация cv2.reprojectImageTo3D, с теми же результатами
  • удаление фона на карте несоответствий вручную
  • работа с uint8 и float32. Перепроецирование работало намного лучше с использованием поплавков.

Полученные изображения:

  • начальная:

  • после калибровки:

  • карта несоответствия (параметры справа):

  • облако точек (выглядит как человек под очень специфическим углом):

Что я могу сделать, чтобы получить полезные результаты? Я даже не знаю, как должны выглядеть изображения. Кажется, моя калибровка отключена? Я чувствую, что изображения действительно плохие (так как перспективное искажение довольно велико), но, к сожалению, мне приходится с ними работать.

Некоторые заглушки кода:

_, self.camera_matrix, self.distortion, _, _ = \
            cv2.calibrateCamera(self.object_points, self.image_points, self.image_size, None, None)

error, _, _, _, _, self.rotation, self.translation, _, _ = \
            cv2.stereoCalibrate(self.camera_left.object_points,
                                self.camera_left.image_points,
                                self.camera_right.image_points,
                                self.camera_left.camera_matrix,
                                self.camera_left.distortion,
                                self.camera_right.camera_matrix,
                                self.camera_right.distortion,
                                self.camera_left.image_size,
                                flags=cv2.CALIB_FIX_INTRINSIC)

self.rotation_left, self.rotation_right, self.perspective_left, self.perspective_right, self.Q, self.roi_left, self.roi_right = \
            cv2.stereoRectify(self.camera_left.camera_matrix,
                              self.camera_left.distortion,
                              self.camera_right.camera_matrix,
                              self.camera_right.distortion,
                              self.camera_left.image_size,
                              self.rotation,
                              self.translation,
                              flags=cv2.CALIB_ZERO_DISPARITY)

self.rotation_left, self.rotation_right, self.perspective_left, self.perspective_right, self.Q, self.roi_left, self.roi_right = \
            cv2.stereoRectify(self.camera_left.camera_matrix,
                              self.camera_left.distortion,
                              self.camera_right.camera_matrix,
                              self.camera_right.distortion,
                              self.camera_left.image_size,
                              self.rotation,
                              self.translation,
                              flags=cv2.CALIB_ZERO_DISPARITY)

self.block_matching = cv2.StereoSGBM().create() # params not mentioned here, but they are set
disparity = self.block_matching.compute(undistorted_left, undistorted_right)
disparity = cv2.convertScaleAbs(disparity, beta=16)

point_cloud = cv2.reprojectImageTo3D(disparity_image, Q)
point_cloud = point_cloud.reshape(-1, point_cloud.shape[-1])
point_cloud = point_cloud[~np.isinf(point_cloud).any(axis=1)]

pcl = open3d.geometry.PointCloud()
pcl.points = open3d.utility.Vector3dVector(point_cloud)
open3d.visualization.draw_geometries([pcl])

0 ответов

Другие вопросы по тегам