| import torch |
| import numpy as np |
|
|
| def get_rot_from_yaw(angle): |
| cy=torch.cos(angle) |
| sy=torch.sin(angle) |
| R=torch.tensor([[cy,0,-sy], |
| [0,1,0], |
| [sy,0,cy]]).float() |
| return R |
|
|
| class Aug_with_Tran(object): |
| def __init__(self,jitter_surface=True,jitter_partial=True,par_jitter_sigma=0.02): |
| self.jitter_surface=jitter_surface |
| self.jitter_partial=jitter_partial |
| self.par_jitter_sigma=par_jitter_sigma |
|
|
| def __call__(self,surface,point,par_points,proj_mat,tran_mat): |
| if surface is not None:surface=torch.mm(surface,tran_mat[0:3,0:3].transpose(0,1))+tran_mat[0:3,3] |
| if point is not None:point=torch.mm(point,tran_mat[0:3,0:3].transpose(0,1))+tran_mat[0:3,3] |
| if par_points is not None:par_points=torch.mm(par_points,tran_mat[0:3,0:3].transpose(0,1))+tran_mat[0:3,3] |
| if proj_mat is not None: |
| '''need to put the augmentation back''' |
| inv_tran_mat = np.linalg.inv(tran_mat) |
| if isinstance(proj_mat, list): |
| for idx, mat in enumerate(proj_mat): |
| mat = np.dot(mat, inv_tran_mat) |
| proj_mat[idx] = mat |
| else: |
| proj_mat = np.dot(proj_mat, inv_tran_mat) |
|
|
| if self.jitter_surface and surface is not None: |
| surface += 0.005 * torch.randn_like(surface) |
| surface.clamp_(min=-1, max=1) |
| if self.jitter_partial and par_points is not None: |
| par_points+=self.par_jitter_sigma * torch.randn_like(par_points) |
|
|
|
|
| return surface,point,par_points,proj_mat |
|
|
|
|
| |
| class Scale_Shift_Rotate(object): |
| def __init__(self, interval=(0.75, 1.25), angle=(-5,5), shift=(-0.1,0.1), use_scale=True,use_whole_scale=False,use_rot=True, |
| use_shift=True,jitter=True,jitter_partial=True,par_jitter_sigma=0.02,rot_shift_surface=True): |
| assert isinstance(interval, tuple) |
| self.interval = interval |
| self.angle=angle |
| self.shift=shift |
| self.jitter = jitter |
| self.jitter_partial=jitter_partial |
| self.rot_shift_surface=rot_shift_surface |
| self.use_scale=use_scale |
| self.use_rot=use_rot |
| self.use_shift=use_shift |
| self.par_jitter_sigma=par_jitter_sigma |
| self.use_whole_scale=use_whole_scale |
|
|
| def __call__(self, surface, point, par_points=None,proj_mat=None): |
| if self.use_scale: |
| scaling = torch.rand(1, 3) * 0.5 + 0.75 |
| else: |
| scaling = torch.ones((1,3)).float() |
| if self.use_shift: |
| shifting = torch.rand(1,3) *(self.shift[1]-self.shift[0])+self.shift[0] |
| else: |
| shifting=np.zeros((1,3)) |
| if self.use_rot: |
| angle=torch.rand(1)*(self.angle[1]-self.angle[0])+self.angle[0] |
| else: |
| angle=torch.tensor((0)) |
| |
| angle=angle/180*np.pi |
| rot_mat=get_rot_from_yaw(angle) |
|
|
| surface = surface * scaling |
| point = point * scaling |
|
|
| scale = (1 / torch.abs(surface).max().item()) * 0.999999 |
| if self.use_whole_scale: |
| scale = scale*(np.random.random()*0.3+0.7) |
| surface *= scale |
| point *= scale |
|
|
| |
|
|
| if self.rot_shift_surface: |
| surface=torch.mm(surface,rot_mat.transpose(0,1)) |
| surface = surface + shifting |
| point=torch.mm(point,rot_mat.transpose(0,1)) |
| point=point+shifting |
|
|
| if par_points is not None: |
| par_points = par_points * scaling |
| par_points=torch.mm(par_points,rot_mat.transpose(0,1)) |
| par_points+=shifting |
| par_points *= scale |
|
|
| post_scale_tran=np.eye(4) |
| post_scale_tran[0,0],post_scale_tran[1,1],post_scale_tran[2,2]=scale,scale,scale |
| shift_tran = np.eye(4) |
| shift_tran[0:3, 3] = shifting |
| rot_tran = np.eye(4) |
| rot_tran[0:3, 0:3] = rot_mat |
| scale_tran = np.eye(4) |
| scale_tran[0, 0], scale_tran[1, 1], scale_tran[2, 2] = scaling[0, 0], scaling[ |
| 0, 1], scaling[0, 2] |
|
|
| |
| tran_mat=np.dot(post_scale_tran,np.dot(shift_tran,np.dot(rot_tran,scale_tran))) |
| |
| |
| if proj_mat is not None: |
| '''need to put the augmentation back''' |
| inv_tran_mat=np.linalg.inv(tran_mat) |
| if isinstance(proj_mat,list): |
| for idx,mat in enumerate(proj_mat): |
| mat=np.dot(mat,inv_tran_mat) |
| proj_mat[idx]=mat |
| else: |
| proj_mat=np.dot(proj_mat,inv_tran_mat) |
|
|
|
|
| if self.jitter: |
| surface += 0.005 * torch.randn_like(surface) |
| surface.clamp_(min=-1, max=1) |
| if self.jitter_partial and par_points is not None: |
| par_points+=self.par_jitter_sigma * torch.randn_like(par_points) |
|
|
| return surface, point, par_points, proj_mat, tran_mat |
|
|
|
|
| class Augment_Points(object): |
| def __init__(self, interval=(0.75, 1.25), angle=(-5,5), shift=(-0.1,0.1), use_scale=True,use_rot=True, |
| use_shift=True,jitter=True,jitter_sigma=0.02): |
| assert isinstance(interval, tuple) |
| self.interval = interval |
| self.angle=angle |
| self.shift=shift |
| self.jitter = jitter |
| self.use_scale=use_scale |
| self.use_rot=use_rot |
| self.use_shift=use_shift |
| self.jitter_sigma=jitter_sigma |
|
|
| def __call__(self, points1,points2): |
| if self.use_scale: |
| scaling = torch.rand(1, 3) * 0.5 + 0.75 |
| else: |
| scaling = torch.ones((1,3)).float() |
| if self.use_shift: |
| shifting = torch.rand(1,3) *(self.shift[1]-self.shift[0])+self.shift[0] |
| else: |
| shifting=np.zeros((1,3)) |
| if self.use_rot: |
| angle=torch.rand(1)*(self.angle[1]-self.angle[0])+self.angle[0] |
| else: |
| angle=torch.tensor((0)) |
| |
| angle=angle/180*np.pi |
| rot_mat=get_rot_from_yaw(angle) |
|
|
| points1 = points1 * scaling |
| points2 = points2 * scaling |
|
|
| |
| scale = min((1 / torch.abs(points1).max().item()) * 0.999999,(1 / torch.abs(points2).max().item()) * 0.999999) |
| points1 *= scale |
| points2 *= scale |
|
|
| points1=torch.mm(points1,rot_mat.transpose(0,1)) |
| points1 = points1 + shifting |
| points2=torch.mm(points2,rot_mat.transpose(0,1)) |
| points2=points2+shifting |
|
|
| if self.jitter: |
| points1 += self.jitter_sigma * torch.randn_like(points1) |
| points2 += self.jitter_sigma * torch.randn_like(points2) |
|
|
| return points1,points2 |