Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to extract removal ground points #37

Open
tuandle opened this issue Jan 18, 2019 · 7 comments
Open

Unable to extract removal ground points #37

tuandle opened this issue Jan 18, 2019 · 7 comments

Comments

@tuandle
Copy link

tuandle commented Jan 18, 2019

Hi @niosus ,
I would like to reproduce your result at Fig3 in your journal paper.
I tried a naive approach to get the removal ground points by changing this line from == to =!

if (dilated.at<uint16_t>(r, c) =! 0)

My understanding is that, with this change, depth_ground_remover should return a Cloud obj contains only ground points. However, when visualizing it, I got the original raw pointcloud.

I definitely miss something here and I greatly appreciate your advice.

@niosus
Copy link
Member

niosus commented Jan 18, 2019

Ok, this might sound a but counter-intuitive, but for the sake of speed I never updated the points in the cloud after removing the ground from the range image. So the cloud is still the same, but every cloud has a range image attached to it, so the image attached to it is not without ground. After your changes this image will contain ground only, but the cloud does not change.

I set the image here:

cloud_copy.projection_ptr()->depth_image() = no_ground_image;

@tuandle
Copy link
Author

tuandle commented Jan 19, 2019

@niosus Thanks for your clarification.
I see that everything is based on the range image for fast computation. What I understand so far for removing ground is as follows:

  1. You remove the ground based on the range image in depth_ground_remover. The processed range image (should contain non-zero values for non-ground points and zero values for ground point) is sent to image_based_clusterer
  2. image_based_clusterer first labels the received range image. It will only label non-ground points (depth pixels with non-zero value). Then it creates a container to store labels and their corresponding points and after that, send the container to the next client.

My approach is like this:

  1. I remove all the non-ground points (switch == to !=). The processed range image contains only the ground (with non-zero values; non-ground points are marked as zero) and is sent to the next step.
  2. I skip the labeling procedure and create a container which stores only 1 label and all the ground points from the received range image.
    I create the container like this:
void OnNewObjectReceived(const Cloud& cloud, const int sender_id) override {
    // generate a projection from a point cloud
    if (!cloud.projection_ptr()) {
      fprintf(stderr, "ERROR: projection not initialized in cloud.\n");
      fprintf(stderr, "INFO: cannot label this cloud.\n");
      return;
    }
    time_utils::Timer timer;
    // create 3d clusters from image labels
    std::unordered_map<uint16_t, Cloud> clusters;
    // assign an arbitrary ground label
    uint16_t label = 2;
    // this depth image should contain only ground points
    const cv::Mat& img_ground = cloud.projection_ptr()->depth_image();
    for (int row = 0; row < img_ground.rows; ++row) {
      for (int col = 0; col < img_ground.cols; ++col) {
        const auto& point_container = cloud.projection_ptr()->at(row, col);
        if (point_container.IsEmpty()) {
          // this is ok, just continue, nothing interesting here, no points.
          continue;
        }
        if (img_ground.at<float>(row, col) == 0) {
          // skip non-ground points
          continue;
        }
        for (const auto& point_idx : point_container.points()) {
          const auto& point = cloud.points()[point_idx];
          clusters[label].push_back(point);
        }
      }
    }

    fprintf(stderr, "INFO: prepared ground clusters in: %lu us\n",
            timer.measure());

    this->ShareDataWithAllClients(clusters);
    fprintf(stderr, "INFO: ground clusters shared: %lu us\n", timer.measure());
  }

I am not sure what I miss here so that the processed pointcloud is exactly as the original?

@tuandle
Copy link
Author

tuandle commented Jan 22, 2019

@niosus any advice, please :)

@niosus
Copy link
Member

niosus commented Jan 22, 2019

@tuandle I'm sorry, I am currently really in a complete lack of time to debug your problem. The idea that you have is valid and should theoretically work, but I cannot look for an error in your code right now. I will keep it here and if I find the time I will look into this, but I cannot promise when this might happen. Sorry for that.

@tuandle
Copy link
Author

tuandle commented Jan 22, 2019

@niosus no problem, thank you for your help anyway :)

@lonlonago
Copy link

@niosus the _para._step is 870, does that means for speed up, you do not use all the points into process?

@seboz123
Copy link

@tuandle Hi I would like to recreate the same thing:
Just printing publishing/ printing the removed ground of the point cloud to evaluate it against other algorithms.
Have you found a solution/implementation yet?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants