## pointnet + + source code learning

Pointnet + + contains the pointnet source code, so just look at pointnet + +

### Overall process

Look at the source code in the form of debug, analyze the change process of power data in the network, and how to extract features

Take batch size = 2 as an example

Input data: 2, 1024, 3

->channel_first 2, 3, 1024

### First SA

First, it was changed back to 21024, 3

Then there are three different radii of MSG

Using query_ball_point() to group

Farthest point sampling

512 points [2512,3] are selected, and then the given r is grouped with the 512 points as the center of the circle,

Group

The operations of the three radii were done separately and finally merged together

Take the first as an example

The data obtained through the grouping of the first radius is [2512,16,3]

Then it was changed to [2,3,16512]

After mlp feature extraction, the result is

[2,64,16,512]

Explain: 2-batchsize 64 channel 16 is the number of points in a group

Find the maximum value again (that is, find the maximum value for each group, which is the same as maxpool in pointnet)

The final result is [2,64512]

This is the result of mlp for the first group

The results of the other two radii are [2128512] and [2128512] Then concat the three results

The final is [2320512]

Second SA

The into SA consists of two parts,

One is the point after farthest point sampling [2,3512], and the result after MLP is [2320512]

The results after MLP are put into the network as part of the features,

The result after extraction is

[2,3128] results of farthest point sampling

[2640128] after MLP

Third SA

[2,3,1]

[21024, 1] after MLP

Final classification

Classify according to the characteristics of [21024,1], and MLP is completed, which is relatively simple.

### Source code

FPS farthest point sampling, each line is annotated, and other codes are relatively simple

Firstly, centroids and distance are defined as subsequent storage center points and distances

Randomly select a point as the beginning of the farthest point,

Then find the distance from all points to this point

A new distance matrix dist is obtained

Compare this distance with distance. If the distance is small, replace the distance result,

Then select the maximum value according to the distance matrix, that is, the value with the maximum distance. Get the corresponding index

When calculating the third point, calculate the distance dist from all points to the second point

Compare with distance. Notice what distance means here. It means the distance from all points to the first point

Compare the two, that is, the distance from all points to the first point and the distance from the second point. Select the smaller distance and update it to distance. Then the distance becomes the shortest distance from all the points to the first point and the second point. Here is the key. I can understand it only by drawing a little

The next point is determined to be the largest one among the nearest ones, and continue the iteration.

def farthest_point_sample(xyz, npoint): """ Input: xyz: pointcloud data, [B, N, 3] npoint: number of samples Return: centroids: sampled pointcloud index, [B, npoint] """ device = xyz.device # B, N, C = xyz.shape# #First define the matrix of the center point and the distance matrix. The center point is our farthest point. The number of sampling points is 512 for the first time centroids = torch.zeros(B, npoint, dtype=torch.long).to(device)#2*512 distance = torch.ones(B, N).to(device) * 1e10 #1024 the distance matrix defined first has a large number #Farthest point, the first farthest point is randomly selected #Random indexes, such as [224518], have two values because batch size is 2 farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device)#In batch, each sample randomly initializes an index of the farthest point # Index in each batch batch_indices = torch.arange(B, dtype=torch.long).to(device) for i in range(npoint): #The first npoint is 512 and the cycle is 512ci centroids[:, i] = farthest #The first sampling point selects the randomly initialized index centroid = xyz[batch_indices, farthest, :].view(B, 1, 3)#Get the coordinates of the current sampling point B*3 dist = torch.sum((xyz - centroid) ** 2, -1)#Calculate the distance between the current sampling point and other points mask = dist < distance#Select the nearest one to update the distance (update and maintain this table), and a mask consisting of bool distance[mask] = dist[mask]# farthest = torch.max(distance, -1)[1]#Recalculate the farthest point index (select the point with the largest distance in the updated table) return centroid