| 214 | |
| 215 | |
| 216 | class PointNet_FP_Module(nn.Module): |
| 217 | def __init__(self, in_channel, mlp, use_points1=False, in_channel_points1=None, if_bn=True): |
| 218 | """ |
| 219 | Args: |
| 220 | in_channel: int, input channel of points2 |
| 221 | mlp: list of int |
| 222 | use_points1: boolean, if use points |
| 223 | in_channel_points1: int, input channel of points1 |
| 224 | """ |
| 225 | super(PointNet_FP_Module, self).__init__() |
| 226 | self.use_points1 = use_points1 |
| 227 | |
| 228 | if use_points1: |
| 229 | in_channel += in_channel_points1 |
| 230 | |
| 231 | last_channel = in_channel |
| 232 | self.mlp_conv = [] |
| 233 | for out_channel in mlp: |
| 234 | self.mlp_conv.append(Conv1d(last_channel, out_channel, if_bn=if_bn)) |
| 235 | last_channel = out_channel |
| 236 | |
| 237 | self.mlp_conv = nn.Sequential(*self.mlp_conv) |
| 238 | |
| 239 | def forward(self, xyz1, xyz2, points1, points2): |
| 240 | """ |
| 241 | Args: |
| 242 | xyz1: Tensor, (B, 3, N) |
| 243 | xyz2: Tensor, (B, 3, M) |
| 244 | points1: Tensor, (B, in_channel, N) |
| 245 | points2: Tensor, (B, in_channel, M) |
| 246 | |
| 247 | Returns:MLP_CONV |
| 248 | new_points: Tensor, (B, mlp[-1], N) |
| 249 | """ |
| 250 | dist, idx = three_nn(xyz1.permute(0, 2, 1).contiguous(), xyz2.permute(0, 2, 1).contiguous()) |
| 251 | dist = torch.clamp_min(dist, 1e-10) # (B, N, 3) |
| 252 | recip_dist = 1.0/dist |
| 253 | norm = torch.sum(recip_dist, 2, keepdim=True).repeat((1, 1, 3)) |
| 254 | weight = recip_dist / norm |
| 255 | interpolated_points = three_interpolate(points2, idx, weight) # B, in_channel, N |
| 256 | |
| 257 | if self.use_points1: |
| 258 | new_points = torch.cat([interpolated_points, points1], 1) |
| 259 | else: |
| 260 | new_points = interpolated_points |
| 261 | |
| 262 | new_points = self.mlp_conv(new_points) |
| 263 | return new_points |
| 264 | |
| 265 | |
| 266 | def square_distance(src, dst): |
nothing calls this directly
no outgoing calls
no test coverage detected