Spaces:
Build error
Build error
""" | |
@Date: 2021/07/27 | |
@description: | |
""" | |
import numpy as np | |
import cv2 | |
import functools | |
from utils.conversion import pixel2lonlat, lonlat2pixel, uv2lonlat, lonlat2uv, pixel2uv | |
def prepare_stretch(w, h): | |
lon = pixel2lonlat(np.array(range(w)), w=w, axis=0) | |
lat = pixel2lonlat(np.array(range(h)), h=h, axis=1) | |
sin_lon = np.sin(lon) | |
cos_lon = np.cos(lon) | |
tan_lat = np.tan(lat) | |
return sin_lon, cos_lon, tan_lat | |
def pano_stretch_image(pano_img, kx, ky, kz): | |
""" | |
Note that this is the inverse mapping, which refers to Equation 3 in HorizonNet paper (the coordinate system in | |
the paper is different from here, xz needs to be swapped) | |
:param pano_img: a panorama image, shape must be [h,w,c] | |
:param kx: stretching along left-right direction | |
:param ky: stretching along up-down direction | |
:param kz: stretching along front-back direction | |
:return: | |
""" | |
w = pano_img.shape[1] | |
h = pano_img.shape[0] | |
sin_lon, cos_lon, tan_lat = prepare_stretch(w, h) | |
n_lon = np.arctan2(sin_lon * kz / kx, cos_lon) | |
n_lat = np.arctan(tan_lat[..., None] * np.sin(n_lon) / sin_lon * kx / ky) | |
n_pu = lonlat2pixel(n_lon, w=w, axis=0, need_round=False) | |
n_pv = lonlat2pixel(n_lat, h=h, axis=1, need_round=False) | |
pixel_map = np.empty((h, w, 2), dtype=np.float32) | |
pixel_map[..., 0] = n_pu | |
pixel_map[..., 1] = n_pv | |
map1 = pixel_map[..., 0] | |
map2 = pixel_map[..., 1] | |
# using wrap mode because it is continues at left or right of panorama | |
new_img = cv2.remap(pano_img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_WRAP) | |
return new_img | |
def pano_stretch_conner(corners, kx, ky, kz): | |
""" | |
:param corners: | |
:param kx: stretching along left-right direction | |
:param ky: stretching along up-down direction | |
:param kz: stretching along front-back direction | |
:return: | |
""" | |
lonlat = uv2lonlat(corners) | |
sin_lon = np.sin(lonlat[..., 0:1]) | |
cos_lon = np.cos(lonlat[..., 0:1]) | |
tan_lat = np.tan(lonlat[..., 1:2]) | |
n_lon = np.arctan2(sin_lon * kx / kz, cos_lon) | |
a = np.bitwise_or(corners[..., 0] == 0.5, corners[..., 0] == 1) | |
b = np.bitwise_not(a) | |
w = np.zeros_like(n_lon) | |
w[b] = np.sin(n_lon[b]) / sin_lon[b] | |
w[a] = kx / kz | |
n_lat = np.arctan(tan_lat * w / kx * ky) | |
lst = [n_lon, n_lat] | |
lonlat = np.concatenate(lst, axis=-1) | |
new_corners = lonlat2uv(lonlat) | |
return new_corners | |
def pano_stretch(pano_img, corners, kx, ky, kz): | |
""" | |
:param pano_img: a panorama image, shape must be [h,w,c] | |
:param corners: | |
:param kx: stretching along left-right direction | |
:param ky: stretching along up-down direction | |
:param kz: stretching along front-back direction | |
:return: | |
""" | |
new_img = pano_stretch_image(pano_img, kx, ky, kz) | |
new_corners = pano_stretch_conner(corners, kx, ky, kz) | |
return new_img, new_corners | |
class PanoDataAugmentation: | |
def __init__(self, aug): | |
self.aug = aug | |
self.parameters = {} | |
def need_aug(self, name): | |
return name in self.aug and self.aug[name] | |
def execute_space_aug(self, corners, image): | |
if image is None: | |
return image | |
if self.aug is None: | |
return corners, image | |
w = image.shape[1] | |
h = image.shape[0] | |
if self.need_aug('STRETCH'): | |
kx = np.random.uniform(1, 2) | |
kx = 1 / kx if np.random.randint(2) == 0 else kx | |
# we found that the ky transform may cause IoU to drop (HorizonNet also only x and z transform) | |
# ky = np.random.uniform(1, 2) | |
# ky = 1 / ky if np.random.randint(2) == 0 else ky | |
ky = 1 | |
kz = np.random.uniform(1, 2) | |
kz = 1 / kz if np.random.randint(2) == 0 else kz | |
image, corners = pano_stretch(image, corners, kx, ky, kz) | |
self.parameters['STRETCH'] = {'kx': kx, 'ky': ky, 'kz': kz} | |
else: | |
self.parameters['STRETCH'] = None | |
if self.need_aug('ROTATE'): | |
d_pu = np.random.randint(w) | |
image = np.roll(image, d_pu, axis=1) | |
corners[..., 0] = (corners[..., 0] + pixel2uv(np.array([d_pu]), w, h)) % pixel2uv(np.array([w]), w, h) | |
self.parameters['ROTATE'] = d_pu | |
else: | |
self.parameters['ROTATE'] = None | |
if self.need_aug('FLIP') and np.random.randint(2) == 0: | |
image = np.flip(image, axis=1).copy() | |
corners[..., 0] = pixel2uv(np.array([w]), w, h) - corners[..., 0] | |
corners = corners[::-1] | |
self.parameters['FLIP'] = True | |
else: | |
self.parameters['FLIP'] = None | |
return corners, image | |
def execute_visual_aug(self, image): | |
if self.need_aug('GAMMA'): | |
p = np.random.uniform(1, 2) | |
if np.random.randint(2) == 0: | |
p = 1 / p | |
image = image ** p | |
self.parameters['GAMMA'] = p | |
else: | |
self.parameters['GAMMA'] = None | |
# The following visual augmentation methods are only implemented but not tested | |
if self.need_aug('HUE') or self.need_aug('SATURATION'): | |
image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV) | |
if self.need_aug('HUE') and np.random.randint(2) == 0: | |
p = np.random.uniform(-0.1, 0.1) | |
image[..., 0] = np.mod(image[..., 0] + p * 180, 180) | |
self.parameters['HUE'] = p | |
else: | |
self.parameters['HUE'] = None | |
if self.need_aug('SATURATION') and np.random.randint(2) == 0: | |
p = np.random.uniform(0.5, 1.5) | |
image[..., 1] = np.clip(image[..., 1] * p, 0, 1) | |
self.parameters['SATURATION'] = p | |
else: | |
self.parameters['SATURATION'] = None | |
image = cv2.cvtColor(image, cv2.COLOR_HSV2RGB) | |
if self.need_aug('CONTRAST') and np.random.randint(2) == 0: | |
p = np.random.uniform(0.9, 1.1) | |
mean = image.mean(axis=0).mean(axis=0) | |
image = (image - mean) * p + mean | |
image = np.clip(image, 0, 1) | |
self.parameters['CONTRAST'] = p | |
else: | |
self.parameters['CONTRAST'] = None | |
return image | |
def execute_aug(self, corners, image): | |
corners, image = self.execute_space_aug(corners, image) | |
if image is not None: | |
image = self.execute_visual_aug(image) | |
return corners, image | |
if __name__ == '__main__1': | |
from tqdm import trange | |
from visualization.floorplan import draw_floorplan | |
from dataset.communal.read import read_image, read_label | |
from utils.time_watch import TimeWatch | |
from utils.conversion import uv2xyz | |
from utils.boundary import corners2boundary | |
np.random.seed(123) | |
pano_img_path = "../../src/dataset/mp3d/image/TbHJrupSAjP_f320ae084f3a447da3e8ab11dd5f9320.png" | |
label_path = "../../src/dataset/mp3d/label/TbHJrupSAjP_f320ae084f3a447da3e8ab11dd5f9320.json" | |
pano_img = read_image(pano_img_path) | |
label = read_label(label_path) | |
corners = label['corners'] | |
ratio = label['ratio'] | |
pano_aug = PanoDataAugmentation(aug={ | |
'STRETCH': True, | |
'ROTATE': True, | |
'FLIP': True, | |
'GAMMA': True, | |
# 'HUE': True, | |
# 'SATURATION': True, | |
# 'CONTRAST': True | |
}) | |
# draw_floorplan(corners, show=True, marker_color=0.5, center_color=0.8, plan_y=1.6, show_radius=8) | |
# draw_boundaries(pano_img, corners_list=[corners], show=True, length=1024, ratio=ratio) | |
w = TimeWatch("test") | |
for i in trange(50000): | |
new_corners, new_pano_img = pano_aug.execute_aug(corners.copy(), pano_img.copy()) | |
# draw_floorplan(uv2xyz(new_corners, plan_y=1.6)[..., ::2], show=True, marker_color=0.5, center_color=0.8, | |
# show_radius=8) | |
# draw_boundaries(new_pano_img, corners_list=[new_corners], show=True, length=1024, ratio=ratio) | |
if __name__ == '__main__': | |
from utils.boundary import corners2boundary | |
from visualization.floorplan import draw_floorplan | |
from utils.boundary import visibility_corners | |
corners = np.array([[0.7664539, 0.7416811], | |
[0.06641078, 0.6521386], | |
[0.30997428, 0.57855356], | |
[0.383300784, 0.58726823], | |
[0.383300775, 0.8005296], | |
[0.5062902, 0.74822706]]) | |
corners = visibility_corners(corners) | |
print(corners) | |
# draw_floorplan(uv2xyz(corners, plan_y=1.6)[..., ::2], show=True, marker_color=0.5, center_color=0.8, | |
# show_radius=8) | |
visible_floor_boundary = corners2boundary(corners, length=256, visible=True) | |
# visible_depth = xyz2depth(uv2xyz(visible_floor_boundary, 1), 1) | |
print(len(visible_floor_boundary)) | |
if __name__ == '__main__0': | |
from visualization.floorplan import draw_floorplan | |
from dataset.communal.read import read_image, read_label | |
from utils.time_watch import TimeWatch | |
from utils.conversion import uv2xyz | |
# np.random.seed(1234) | |
pano_img_path = "../../src/dataset/mp3d/image/VVfe2KiqLaN_35b41dcbfcf84f96878f6ca28c70e5af.png" | |
label_path = "../../src/dataset/mp3d/label/VVfe2KiqLaN_35b41dcbfcf84f96878f6ca28c70e5af.json" | |
pano_img = read_image(pano_img_path) | |
label = read_label(label_path) | |
corners = label['corners'] | |
ratio = label['ratio'] | |
# draw_floorplan(corners, show=True, marker_color=0.5, center_color=0.8, plan_y=1.6, show_radius=8) | |
w = TimeWatch() | |
for i in range(5): | |
kx = np.random.uniform(1, 2) | |
kx = 1 / kx if np.random.randint(2) == 0 else kx | |
ky = np.random.uniform(1, 2) | |
ky = 1 / ky if np.random.randint(2) == 0 else ky | |
kz = np.random.uniform(1, 2) | |
kz = 1 / kz if np.random.randint(2) == 0 else kz | |
new_corners = pano_stretch_conner(corners.copy(), kx, ky, kz) | |
draw_floorplan(uv2xyz(new_corners, plan_y=1.6)[..., ::2], show=True, marker_color=0.5, center_color=0.8, | |
show_radius=8) | |