mirror of
				https://github.com/facebookresearch/pytorch3d.git
				synced 2025-11-04 18:02:14 +08:00 
			
		
		
		
	Fix coordinate system conventions in point cloud renderer
Summary: Applying the changes added for mesh rasterization to ensure that +Y is up and +X is left so that the coordinate system is right handed. Also updated the diagram in the docs to indicate that (0,0) is in the top left hand corner. Reviewed By: gkioxari Differential Revision: D20394849 fbshipit-source-id: cfb7c79090eb1f55ad38b92327a74a70a8dc541e
This commit is contained in:
		
							parent
							
								
									32ad869dea
								
							
						
					
					
						commit
						d01e722849
					
				
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB  | 
@ -208,7 +208,7 @@ __global__ void RasterizeMeshesNaiveCudaKernel(
 | 
			
		||||
    const int n = i / (H * W); // batch index.
 | 
			
		||||
    const int pix_idx = i % (H * W);
 | 
			
		||||
 | 
			
		||||
    // Determine ordering based on axis convention.
 | 
			
		||||
    // Reverse ordering of X and Y axes
 | 
			
		||||
    const int yi = H - 1 - pix_idx / W;
 | 
			
		||||
    const int xi = W - 1 - pix_idx % W;
 | 
			
		||||
 | 
			
		||||
@ -353,7 +353,7 @@ __global__ void RasterizeMeshesBackwardCudaKernel(
 | 
			
		||||
    const int n = t_i / (H * W); // batch index.
 | 
			
		||||
    const int pix_idx = t_i % (H * W);
 | 
			
		||||
 | 
			
		||||
    // Determine ordering based on axis convention.
 | 
			
		||||
    // Reverse ordering of X and Y axes.
 | 
			
		||||
    const int yi = H - 1 - pix_idx / W;
 | 
			
		||||
    const int xi = W - 1 - pix_idx % W;
 | 
			
		||||
 | 
			
		||||
@ -557,8 +557,8 @@ __global__ void RasterizeMeshesCoarseCudaKernel(
 | 
			
		||||
        // need to add/subtract a half pixel to get the true extent of the bin.
 | 
			
		||||
        // Reverse ordering of Y axis so that +Y is upwards in the image.
 | 
			
		||||
        const int yidx = num_bins - by;
 | 
			
		||||
        float bin_y_max = PixToNdc(yidx * bin_size - 1, H) + half_pix;
 | 
			
		||||
        float bin_y_min = PixToNdc((yidx - 1) * bin_size, H) - half_pix;
 | 
			
		||||
        const float bin_y_max = PixToNdc(yidx * bin_size - 1, H) + half_pix;
 | 
			
		||||
        const float bin_y_min = PixToNdc((yidx - 1) * bin_size, H) - half_pix;
 | 
			
		||||
 | 
			
		||||
        const bool y_overlap = (ymin <= bin_y_max) && (bin_y_min < ymax);
 | 
			
		||||
 | 
			
		||||
@ -566,8 +566,8 @@ __global__ void RasterizeMeshesCoarseCudaKernel(
 | 
			
		||||
          // X coordinate of the left and right of the bin.
 | 
			
		||||
          // Reverse ordering of x axis so that +X is left.
 | 
			
		||||
          const int xidx = num_bins - bx;
 | 
			
		||||
          float bin_x_max = PixToNdc(xidx * bin_size - 1, W) + half_pix;
 | 
			
		||||
          float bin_x_min = PixToNdc((xidx - 1) * bin_size, W) - half_pix;
 | 
			
		||||
          const float bin_x_max = PixToNdc(xidx * bin_size - 1, W) + half_pix;
 | 
			
		||||
          const float bin_x_min = PixToNdc((xidx - 1) * bin_size, W) - half_pix;
 | 
			
		||||
 | 
			
		||||
          const bool x_overlap = (xmin <= bin_x_max) && (bin_x_min < xmax);
 | 
			
		||||
          if (y_overlap && x_overlap) {
 | 
			
		||||
 | 
			
		||||
@ -473,11 +473,11 @@ torch::Tensor RasterizeMeshesCoarseCpu(
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Shift the bin down for the next loop iteration.
 | 
			
		||||
        // Shift the bin to the left for the next loop iteration.
 | 
			
		||||
        bin_x_max = bin_x_min;
 | 
			
		||||
        bin_x_min = bin_x_min - bin_width;
 | 
			
		||||
      }
 | 
			
		||||
      // Shift the bin left for the next loop iteration.
 | 
			
		||||
      // Shift the bin down for the next loop iteration.
 | 
			
		||||
      bin_y_max = bin_y_min;
 | 
			
		||||
      bin_y_min = bin_y_min - bin_width;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -94,8 +94,10 @@ __global__ void RasterizePointsNaiveCudaKernel(
 | 
			
		||||
    // Convert linear index to 3D index
 | 
			
		||||
    const int n = i / (S * S); // Batch index
 | 
			
		||||
    const int pix_idx = i % (S * S);
 | 
			
		||||
    const int yi = pix_idx / S;
 | 
			
		||||
    const int xi = pix_idx % S;
 | 
			
		||||
 | 
			
		||||
    // Reverse ordering of X and Y axes.
 | 
			
		||||
    const int yi = S - 1 - pix_idx / S;
 | 
			
		||||
    const int xi = S - 1 - pix_idx % S;
 | 
			
		||||
 | 
			
		||||
    const float xf = PixToNdc(xi, S);
 | 
			
		||||
    const float yf = PixToNdc(yi, S);
 | 
			
		||||
@ -126,7 +128,7 @@ __global__ void RasterizePointsNaiveCudaKernel(
 | 
			
		||||
          points, p_idx, q_size, q_max_z, q_max_idx, q, radius2, xf, yf, K);
 | 
			
		||||
    }
 | 
			
		||||
    BubbleSort(q, q_size);
 | 
			
		||||
    int idx = n * S * S * K + yi * S * K + xi * K;
 | 
			
		||||
    int idx = n * S * S * K + pix_idx * K;
 | 
			
		||||
    for (int k = 0; k < q_size; ++k) {
 | 
			
		||||
      point_idxs[idx + k] = q[k].idx;
 | 
			
		||||
      zbuf[idx + k] = q[k].z;
 | 
			
		||||
@ -258,18 +260,23 @@ __global__ void RasterizePointsCoarseCudaKernel(
 | 
			
		||||
        // Get y extent for the bin. PixToNdc gives us the location of
 | 
			
		||||
        // the center of each pixel, so we need to add/subtract a half
 | 
			
		||||
        // pixel to get the true extent of the bin.
 | 
			
		||||
        const float by0 = PixToNdc(by * bin_size, S) - half_pix;
 | 
			
		||||
        const float by1 = PixToNdc((by + 1) * bin_size - 1, S) + half_pix;
 | 
			
		||||
        const bool y_overlap = (py0 <= by1) && (by0 <= py1);
 | 
			
		||||
        // Reverse ordering of Y axis so that +Y is upwards in the image.
 | 
			
		||||
        const int yidx = num_bins - by;
 | 
			
		||||
        const float bin_y_max = PixToNdc(yidx * bin_size - 1, S) + half_pix;
 | 
			
		||||
        const float bin_y_min = PixToNdc((yidx - 1) * bin_size, S) - half_pix;
 | 
			
		||||
 | 
			
		||||
        const bool y_overlap = (py0 <= bin_y_max) && (bin_y_min <= py1);
 | 
			
		||||
        if (!y_overlap) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
        for (int bx = 0; bx < num_bins; ++bx) {
 | 
			
		||||
          // Get x extent for the bin; again we need to adjust the
 | 
			
		||||
          // output of PixToNdc by half a pixel.
 | 
			
		||||
          const float bx0 = PixToNdc(bx * bin_size, S) - half_pix;
 | 
			
		||||
          const float bx1 = PixToNdc((bx + 1) * bin_size - 1, S) + half_pix;
 | 
			
		||||
          const bool x_overlap = (px0 <= bx1) && (bx0 <= px1);
 | 
			
		||||
          // Reverse ordering of x axis so that +X is left.
 | 
			
		||||
          const int xidx = num_bins - bx;
 | 
			
		||||
          const float bin_x_max = PixToNdc(xidx * bin_size - 1, S) + half_pix;
 | 
			
		||||
          const float bin_x_min = PixToNdc((xidx - 1) * bin_size, S) - half_pix;
 | 
			
		||||
          const bool x_overlap = (px0 <= bin_x_max) && (bin_x_min <= px1);
 | 
			
		||||
          if (x_overlap) {
 | 
			
		||||
            binmask.set(by, bx, p);
 | 
			
		||||
          }
 | 
			
		||||
@ -395,8 +402,14 @@ __global__ void RasterizePointsFineCudaKernel(
 | 
			
		||||
 | 
			
		||||
    if (yi >= S || xi >= S)
 | 
			
		||||
      continue;
 | 
			
		||||
    const float xf = PixToNdc(xi, S);
 | 
			
		||||
    const float yf = PixToNdc(yi, S);
 | 
			
		||||
 | 
			
		||||
    // Reverse ordering of the X and Y axis so that
 | 
			
		||||
    // in the image +Y is pointing up and +X is pointing left.
 | 
			
		||||
    const int yidx = S - 1 - yi;
 | 
			
		||||
    const int xidx = S - 1 - xi;
 | 
			
		||||
 | 
			
		||||
    const float xf = PixToNdc(xidx, S);
 | 
			
		||||
    const float yf = PixToNdc(yidx, S);
 | 
			
		||||
 | 
			
		||||
    // This part looks like the naive rasterization kernel, except we use
 | 
			
		||||
    // bin_points to only look at a subset of points already known to fall
 | 
			
		||||
@ -493,8 +506,12 @@ __global__ void RasterizePointsBackwardCudaKernel(
 | 
			
		||||
    const int xk = yxk % (W * K);
 | 
			
		||||
    const int xi = xk / K;
 | 
			
		||||
    // k = xk % K (We don't actually need k, but this would be it.)
 | 
			
		||||
    const float xf = PixToNdc(xi, W);
 | 
			
		||||
    const float yf = PixToNdc(yi, H);
 | 
			
		||||
    // Reverse ordering of X and Y axes.
 | 
			
		||||
    const int yidx = H - 1 - yi;
 | 
			
		||||
    const int xidx = W - 1 - xi;
 | 
			
		||||
 | 
			
		||||
    const float xf = PixToNdc(xidx, W);
 | 
			
		||||
    const float yf = PixToNdc(yidx, H);
 | 
			
		||||
 | 
			
		||||
    const int p = idxs[i];
 | 
			
		||||
    if (p < 0)
 | 
			
		||||
 | 
			
		||||
@ -47,9 +47,16 @@ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> RasterizePointsNaiveCpu(
 | 
			
		||||
        (point_start_idx + num_points_per_cloud[n].item().to<int32_t>());
 | 
			
		||||
 | 
			
		||||
    for (int yi = 0; yi < S; ++yi) {
 | 
			
		||||
      float yf = PixToNdc(yi, S);
 | 
			
		||||
      // Reverse the order of yi so that +Y is pointing upwards in the image.
 | 
			
		||||
      const int yidx = S - 1 - yi;
 | 
			
		||||
      const float yf = PixToNdc(yidx, S);
 | 
			
		||||
 | 
			
		||||
      for (int xi = 0; xi < S; ++xi) {
 | 
			
		||||
        float xf = PixToNdc(xi, S);
 | 
			
		||||
        // Reverse the order of xi so that +X is pointing to the left in the
 | 
			
		||||
        // image.
 | 
			
		||||
        const int xidx = S - 1 - xi;
 | 
			
		||||
        const float xf = PixToNdc(xidx, S);
 | 
			
		||||
 | 
			
		||||
        // Use a priority queue to hold (z, idx, r)
 | 
			
		||||
        std::priority_queue<std::tuple<float, int, float>> q;
 | 
			
		||||
        for (int p = point_start_idx; p < point_stop_idx; ++p) {
 | 
			
		||||
@ -118,11 +125,15 @@ torch::Tensor RasterizePointsCoarseCpu(
 | 
			
		||||
    const int point_stop_idx =
 | 
			
		||||
        (point_start_idx + num_points_per_cloud[n].item().to<int32_t>());
 | 
			
		||||
 | 
			
		||||
    float bin_y_min = -1.0f;
 | 
			
		||||
    float bin_y_max = bin_y_min + bin_width;
 | 
			
		||||
    float bin_y_max = 1.0f;
 | 
			
		||||
    float bin_y_min = bin_y_max - bin_width;
 | 
			
		||||
 | 
			
		||||
    // Iterate through the horizontal bins from top to bottom.
 | 
			
		||||
    for (int by = 0; by < B; by++) {
 | 
			
		||||
      float bin_x_min = -1.0f;
 | 
			
		||||
      float bin_x_max = bin_x_min + bin_width;
 | 
			
		||||
      float bin_x_max = 1.0f;
 | 
			
		||||
      float bin_x_min = bin_x_max - bin_width;
 | 
			
		||||
 | 
			
		||||
      // Iterate through bins on this horizontal line, left to right.
 | 
			
		||||
      for (int bx = 0; bx < B; bx++) {
 | 
			
		||||
        int32_t points_hit = 0;
 | 
			
		||||
        for (int p = point_start_idx; p < point_stop_idx; ++p) {
 | 
			
		||||
@ -136,6 +147,7 @@ torch::Tensor RasterizePointsCoarseCpu(
 | 
			
		||||
          float point_x_max = px + radius;
 | 
			
		||||
          float point_y_min = py - radius;
 | 
			
		||||
          float point_y_max = py + radius;
 | 
			
		||||
 | 
			
		||||
          // Use a half-open interval so that points exactly on the
 | 
			
		||||
          // boundary between bins will fall into exactly one bin.
 | 
			
		||||
          bool x_hit = (point_x_min <= bin_x_max) && (bin_x_min <= point_x_max);
 | 
			
		||||
@ -154,13 +166,13 @@ torch::Tensor RasterizePointsCoarseCpu(
 | 
			
		||||
        // Record the number of points found in this bin
 | 
			
		||||
        points_per_bin_a[n][by][bx] = points_hit;
 | 
			
		||||
 | 
			
		||||
        // Shift the bin to the right for the next loop iteration
 | 
			
		||||
        bin_x_min = bin_x_max;
 | 
			
		||||
        bin_x_max = bin_x_min + bin_width;
 | 
			
		||||
        // Shift the bin to the left for the next loop iteration.
 | 
			
		||||
        bin_x_max = bin_x_min;
 | 
			
		||||
        bin_x_min = bin_x_min - bin_width;
 | 
			
		||||
      }
 | 
			
		||||
      // Shift the bin down for the next loop iteration
 | 
			
		||||
      bin_y_min = bin_y_max;
 | 
			
		||||
      bin_y_max = bin_y_min + bin_width;
 | 
			
		||||
      // Shift the bin down for the next loop iteration.
 | 
			
		||||
      bin_y_max = bin_y_min;
 | 
			
		||||
      bin_y_min = bin_y_min - bin_width;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return bin_points;
 | 
			
		||||
@ -193,9 +205,18 @@ torch::Tensor RasterizePointsBackwardCpu(
 | 
			
		||||
 | 
			
		||||
  for (int n = 0; n < N; ++n) { // Loop over images in the batch
 | 
			
		||||
    for (int y = 0; y < H; ++y) { // Loop over rows in the image
 | 
			
		||||
      const float yf = PixToNdc(y, H);
 | 
			
		||||
      // Reverse the order of yi so that +Y is pointing upwards in the image.
 | 
			
		||||
      const int yidx = H - 1 - y;
 | 
			
		||||
      // Y coordinate of the top of the pixel.
 | 
			
		||||
      const float yf = PixToNdc(yidx, H);
 | 
			
		||||
 | 
			
		||||
      // Iterate through pixels on this horizontal line, left to right.
 | 
			
		||||
      for (int x = 0; x < W; ++x) { // Loop over pixels in the row
 | 
			
		||||
        const float xf = PixToNdc(x, W);
 | 
			
		||||
 | 
			
		||||
        // Reverse the order of xi so that +X is pointing to the left in the
 | 
			
		||||
        // image.
 | 
			
		||||
        const int xidx = W - 1 - x;
 | 
			
		||||
        const float xf = PixToNdc(xidx, W);
 | 
			
		||||
        for (int k = 0; k < K; ++k) { // Loop over points for the pixel
 | 
			
		||||
          const int p = idxs_a[n][y][x][k];
 | 
			
		||||
          if (p < 0) {
 | 
			
		||||
 | 
			
		||||
@ -283,7 +283,7 @@ def rasterize_meshes_python(
 | 
			
		||||
                # X coordinate of one end of the image. Reverse the ordering
 | 
			
		||||
                # of xi so that +X is pointing to the left in the image.
 | 
			
		||||
                xfix = W - 1 - xi
 | 
			
		||||
                xf = pix_to_ndc(xfix, H)
 | 
			
		||||
                xf = pix_to_ndc(xfix, W)
 | 
			
		||||
                top_k_points = []
 | 
			
		||||
 | 
			
		||||
                # Check whether each face in the mesh affects this pixel.
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user