|
|
import numpy as np |
|
|
from scipy.ndimage import map_coordinates |
|
|
import cv2 |
|
|
|
|
|
|
|
|
|
|
|
class Equirec2Cube: |
|
|
def __init__(self, equ_h, equ_w, face_w): |
|
|
''' |
|
|
equ_h: int, height of the equirectangular image |
|
|
equ_w: int, width of the equirectangular image |
|
|
face_w: int, the length of each face of the cubemap |
|
|
''' |
|
|
|
|
|
self.equ_h = equ_h |
|
|
self.equ_w = equ_w |
|
|
self.face_w = face_w |
|
|
|
|
|
self._xyzcube() |
|
|
self._xyz2coor() |
|
|
|
|
|
|
|
|
cosmap = 1 / np.sqrt((2 * self.grid[..., 0]) ** 2 + (2 * self.grid[..., 1]) ** 2 + 1) |
|
|
self.cosmaps = np.concatenate(6 * [cosmap], axis=1)[..., np.newaxis] |
|
|
|
|
|
def _xyzcube(self): |
|
|
''' |
|
|
Compute the xyz cordinates of the unit cube in [F R B L U D] format. |
|
|
''' |
|
|
self.xyz = np.zeros((self.face_w, self.face_w * 6, 3), np.float32) |
|
|
rng = np.linspace(-0.5, 0.5, num=self.face_w, dtype=np.float32) |
|
|
self.grid = np.stack(np.meshgrid(rng, -rng), -1) |
|
|
|
|
|
|
|
|
self.xyz[:, 0 * self.face_w:1 * self.face_w, [0, 1]] = self.grid |
|
|
self.xyz[:, 0 * self.face_w:1 * self.face_w, 2] = 0.5 |
|
|
|
|
|
|
|
|
self.xyz[:, 1 * self.face_w:2 * self.face_w, [2, 1]] = self.grid[:, ::-1] |
|
|
self.xyz[:, 1 * self.face_w:2 * self.face_w, 0] = 0.5 |
|
|
|
|
|
|
|
|
self.xyz[:, 2 * self.face_w:3 * self.face_w, [0, 1]] = self.grid[:, ::-1] |
|
|
self.xyz[:, 2 * self.face_w:3 * self.face_w, 2] = -0.5 |
|
|
|
|
|
|
|
|
self.xyz[:, 3 * self.face_w:4 * self.face_w, [2, 1]] = self.grid |
|
|
self.xyz[:, 3 * self.face_w:4 * self.face_w, 0] = -0.5 |
|
|
|
|
|
|
|
|
self.xyz[:, 4 * self.face_w:5 * self.face_w, [0, 2]] = self.grid[::-1, :] |
|
|
self.xyz[:, 4 * self.face_w:5 * self.face_w, 1] = 0.5 |
|
|
|
|
|
|
|
|
self.xyz[:, 5 * self.face_w:6 * self.face_w, [0, 2]] = self.grid |
|
|
self.xyz[:, 5 * self.face_w:6 * self.face_w, 1] = -0.5 |
|
|
|
|
|
def _xyz2coor(self): |
|
|
|
|
|
|
|
|
x, y, z = np.split(self.xyz, 3, axis=-1) |
|
|
lon = np.arctan2(x, z) |
|
|
c = np.sqrt(x ** 2 + z ** 2) |
|
|
lat = np.arctan2(y, c) |
|
|
|
|
|
|
|
|
self.coor_x = (lon / (2 * np.pi) + 0.5) * self.equ_w - 0.5 |
|
|
self.coor_y = (-lat / np.pi + 0.5) * self.equ_h - 0.5 |
|
|
|
|
|
def sample_equirec(self, e_img, order=0): |
|
|
pad_u = np.roll(e_img[[0]], self.equ_w // 2, 1) |
|
|
pad_d = np.roll(e_img[[-1]], self.equ_w // 2, 1) |
|
|
e_img = np.concatenate([e_img, pad_d, pad_u], 0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return map_coordinates(e_img, [self.coor_y, self.coor_x], |
|
|
order=order, mode='wrap')[..., 0] |
|
|
|
|
|
def run(self, equ_img, equ_dep=None): |
|
|
|
|
|
h, w = equ_img.shape[:2] |
|
|
if h != self.equ_h or w != self.equ_w: |
|
|
equ_img = cv2.resize(equ_img, (self.equ_w, self.equ_h)) |
|
|
if equ_dep is not None: |
|
|
equ_dep = cv2.resize(equ_dep, (self.equ_w, self.equ_h), interpolation=cv2.INTER_NEAREST) |
|
|
|
|
|
cube_img = np.stack([self.sample_equirec(equ_img[..., i], order=1) |
|
|
for i in range(equ_img.shape[2])], axis=-1) |
|
|
|
|
|
if equ_dep is not None: |
|
|
cube_dep = np.stack([self.sample_equirec(equ_dep[..., i], order=0) |
|
|
for i in range(equ_dep.shape[2])], axis=-1) |
|
|
cube_dep = cube_dep * self.cosmaps |
|
|
|
|
|
if equ_dep is not None: |
|
|
return cube_img, cube_dep |
|
|
else: |
|
|
return cube_img |