[docs]classSimSenseComponent(Component):def__init__(self,rgb_resolution:tuple,ir_resolution:tuple,rgb_intrinsic:np.ndarray,ir_intrinsic:np.ndarray,trans_pose_l:Pose,trans_pose_r:Pose,min_depth:float,max_depth:float,ir_noise_seed:int,ir_speckle_noise:float,ir_thermal_noise:float,rectified:bool,census_width:int,census_height:int,max_disp:int,block_width:int,block_height:int,p1_penalty:int,p2_penalty:int,uniqueness_ratio:int,lr_max_diff:int,median_filter_size:int,depth_dilation:bool,):super().__init__()# Instance checkifnotisinstance(rgb_resolution[0],int)ornotisinstance(rgb_resolution[1],int):raiseTypeError("RGB resolution (width and height) must be integer")if(notisinstance(ir_resolution[0],int)ornotisinstance(ir_resolution[1],int)orir_resolution[0]<32orir_resolution[1]<32):raiseTypeError("Infrared resolution (width and height) must be integer and no less than 32")ifir_speckle_noise>0andir_thermal_noise<=0:raiseTypeError("ir_speckle_noise > 0, Infrared noise simulation is on. ir_thermal_noise must also be positive")if(notisinstance(census_width,int)ornotisinstance(census_height,int)orcensus_width<=0orcensus_height<=0orcensus_width%2==0orcensus_height%2==0orcensus_width*census_height>65):raiseTypeError("census_width and census_height must be positive odd integers and their product should be no larger than 65")ifnotisinstance(max_disp,int)ormax_disp<32ormax_disp>1024:raiseTypeError("max_disp must be integer and within range [32, 1024]")if(notisinstance(block_width,int)ornotisinstance(block_height,int)orblock_width<=0orblock_height<=0orblock_width%2==0orblock_height%2==0orblock_width*block_height>256):raiseTypeError("block_width and block_height must be positive odd integers and their product should be no larger than 256")if(notisinstance(p1_penalty,int)ornotisinstance(p2_penalty,int)orp1_penalty<=0orp2_penalty<=0orp1_penalty>=p2_penaltyorp2_penalty>=224):raiseTypeError("p1_penalty must be positive integer less than p2_penalty and p2_penalty be positive integer less than 224")if(notisinstance(uniqueness_ratio,int)oruniqueness_ratio<0oruniqueness_ratio>255):raiseTypeError("uniqueness_ratio must be positive integer and no larger than 255")ifnotisinstance(lr_max_diff,int)orlr_max_diff<-1orlr_max_diff>255:raiseTypeError("lr_max_diff must be integer and within the range [0, 255]")if(median_filter_size!=1andmedian_filter_size!=3andmedian_filter_size!=5andmedian_filter_size!=7):raiseTypeError("Median filter size choices are 1, 3, 5, 7")self.rgb_resolution=rgb_resolutionself.ir_resolution=ir_resolutionself.rgb_intrinsic=rgb_intrinsicself.ir_intrinsic=ir_intrinsicself.trans_pose_l=trans_pose_lself.trans_pose_r=trans_pose_rself.min_depth=min_depthself.max_depth=max_depthself.ir_noise_seed=ir_noise_seedself.ir_speckle_noise=ir_speckle_noiseself.ir_thermal_noise=ir_thermal_noiseself.rectified=rectifiedself.census_width=census_widthself.census_height=census_heightself.max_disp=max_dispself.block_width=block_widthself.block_height=block_heightself.p1_penalty=p1_penaltyself.p2_penalty=p2_penaltyself.uniqueness_ratio=uniqueness_ratioself.lr_max_diff=lr_max_diffself.median_filter_size=median_filter_sizeself.depth_dilation=depth_dilationself._default_speckle_shape=1333.33self._default_gaussian_sigma=0.25self._default_gaussian_mu=0self._engine=None
[docs]defon_add_to_scene(self,scene):importcv2ifself.ir_speckle_noise==0:speckle_shape=0else:speckle_shape=self._default_speckle_shape/self.ir_speckle_noisespeckle_scale=self.ir_speckle_noise/self._default_speckle_shapegaussian_mu=self._default_gaussian_mugaussian_sigma=self._default_gaussian_sigma*self.ir_thermal_noise# Depth computing engineir_size,rgb_size=self.ir_resolution,self.rgb_resolutionir_intrinsic=self.ir_intrinsic.astype(float)rgb_intrinsic=self.rgb_intrinsic.astype(float)rgb_pose=Pose()# Dummy pose for deriving extrinsic matricesrgb_extrinsic=self._pose2cv2ex(rgb_pose)l_extrinsic=self._pose2cv2ex(rgb_pose*self.trans_pose_l)r_extrinsic=self._pose2cv2ex(rgb_pose*self.trans_pose_r)l2r=r_extrinsic@np.linalg.inv(l_extrinsic).astype(float)l2rgb=rgb_extrinsic@np.linalg.inv(l_extrinsic).astype(float)r1,r2,p1,p2,q,_,_=cv2.stereoRectify(cameraMatrix1=ir_intrinsic,distCoeffs1=None,cameraMatrix2=ir_intrinsic,distCoeffs2=None,imageSize=ir_size,R=l2r[:3,:3],T=l2r[:3,3:],alpha=1.0,newImageSize=ir_size,)f_len=q[2][3]# focal length of the left camera in metersb_len=1.0/q[3][2]# baseline length in metersmap_l=cv2.initUndistortRectifyMap(ir_intrinsic,None,r1,p1,ir_size,cv2.CV_32F)map_r=cv2.initUndistortRectifyMap(ir_intrinsic,None,r2,p2,ir_size,cv2.CV_32F)map_lx,map_ly=map_lmap_rx,map_ry=map_ra1,a2,a3,b=self._get_registration_mat(ir_size,ir_intrinsic,rgb_intrinsic,l2rgb)rgb_fx=rgb_intrinsic[0][0]rgb_fy=rgb_intrinsic[1][1]rgb_skew=rgb_intrinsic[0][1]rgb_cx=rgb_intrinsic[0][2]rgb_cy=rgb_intrinsic[1][2]self._engine=DepthSensorEngine(ir_size[1],ir_size[0],rgb_size[1],rgb_size[0],f_len,b_len,self.min_depth,self.max_depth,self.ir_noise_seed,speckle_shape,speckle_scale,gaussian_mu,gaussian_sigma,self.rectified,self.census_width,self.census_height,self.max_disp,self.block_width,self.block_height,self.p1_penalty,self.p2_penalty,self.uniqueness_ratio,self.lr_max_diff,self.median_filter_size,map_lx,map_ly,map_rx,map_ry,a1,a2,a3,b[0],b[1],b[2],self.depth_dilation,rgb_fx,rgb_fy,rgb_skew,rgb_cx,rgb_cy,)
[docs]defcompute(self,left:Union[np.ndarray,CudaArray],right:Union[np.ndarray,CudaArray],bbox_start:tuple=None,bbox_size:tuple=None,)->None:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")ifbbox_startisnotNoneandbbox_sizeisnotNone:self._engine.compute(left,right,True,*bbox_start,*bbox_size)else:self._engine.compute(left,right,False,0,0,0,0)
[docs]defget_ndarray(self)->np.ndarray:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")returnself._engine.get_ndarray()
[docs]defget_cuda(self)->CudaArray:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")returnself._engine.get_cuda()
[docs]defget_point_cloud_ndarray(self)->np.ndarray:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")returnself._engine.get_point_cloud_ndarray()
[docs]defget_point_cloud_cuda(self)->CudaArray:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")returnself._engine.get_point_cloud_cuda()
[docs]defget_rgb_point_cloud_ndarray(self,rgba_cuda:CudaArray)->np.ndarray:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")returnself._engine.get_rgb_point_cloud_ndarray(rgba_cuda)
[docs]defget_rgb_point_cloud_cuda(self,rgba_cuda:CudaArray)->CudaArray:ifself._engineisNone:raiseRuntimeError("simsense component is not added to scene")returnself._engine.get_rgb_point_cloud_cuda(rgba_cuda)
@staticmethoddef_get_registration_mat(ir_size,ir_intrinsic,rgb_intrinsic,ir2rgb):R=ir2rgb[:3,:3]t=ir2rgb[:3,3:]w,h=ir_sizex=np.arange(w)y=np.arange(h)u,v=np.meshgrid(x,y)w=np.ones_like(u)pixel_coords=np.stack([u,v,w],axis=-1)# pixel_coords[y, x] is (x, y, 1)A=np.einsum("ij,hwj->hwi",rgb_intrinsic@R@np.linalg.inv(ir_intrinsic),pixel_coords)B=rgb_intrinsic@treturnA[...,0],A[...,1],A[...,2],B@staticmethoddef_pose2cv2ex(pose):ros2opencv=np.array([[0.0,-1.0,0.0,0.0],[0.0,0.0,-1.0,0.0],[1.0,0.0,0.0,0.0],[0.0,0.0,0.0,1.0],],dtype=float,)returnros2opencv@np.linalg.inv(pose.to_transformation_matrix())