Карта диспаратности с облаком точек отключена - PullRequest
1 голос
/ 18 марта 2020

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

То, что я пробовал:

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

Результирующие изображения:

  • начальные:
    Left Image Right Image

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

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

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

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

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

_, 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])
...