PointViewSet PMFFilter::run(PointViewPtr input) { bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process PMFFilter...\n"; auto idx = processGround(input); PointViewSet viewSet; if (!idx.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Debug2) << "Labeled " << idx.size() << " ground returns!\n"; // set the classification label of ground returns as 2 // (corresponding to ASPRS LAS specification) for (const auto& i : idx) { input->setField(Dimension::Id::Classification, i, 2); } viewSet.insert(input); } if (m_extract) { log()->get(LogLevel::Debug2) << "Extracted " << idx.size() << " ground returns!\n"; // create new PointView containing only ground returns PointViewPtr output = input->makeNew(); for (const auto& i : idx) { output->appendPoint(*input, i); } viewSet.erase(input); viewSet.insert(output); } } else { if (idx.empty()) log()->get(LogLevel::Debug2) << "Filtered cloud has no ground returns!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Debug2) << "Must choose --classify or --extract\n"; // return the input buffer unchanged viewSet.insert(input); } return viewSet; }
PointViewSet SMRFilter::run(PointViewPtr view) { log()->get(LogLevel::Info) << "run: Process SMRFilter...\n"; std::vector<PointId> idx = processGround(view); PointViewSet viewSet; if (!idx.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Info) << "run: Labeled " << idx.size() << " ground returns!\n"; // set the classification label of ground returns as 2 // (corresponding to ASPRS LAS specification) for (const auto& i : idx) { view->setField(Dimension::Id::Classification, i, 2); } viewSet.insert(view); } if (m_extract) { log()->get(LogLevel::Info) << "run: Extracted " << idx.size() << " ground returns!\n"; // create new PointView containing only ground returns PointViewPtr output = view->makeNew(); for (const auto& i : idx) { output->appendPoint(*view, i); } viewSet.erase(view); viewSet.insert(output); } } else { if (idx.empty()) log()->get(LogLevel::Info) << "run: Filtered cloud has no ground returns!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Info) << "run: Must choose --classify or --extract\n"; // return the view buffer unchanged viewSet.insert(view); } return viewSet; }
PointViewSet MADFilter::run(PointViewPtr view) { using namespace Dimension; PointViewSet viewSet; PointViewPtr output = view->makeNew(); auto estimate_median = [](std::vector<double> vals) { std::nth_element(vals.begin(), vals.begin()+vals.size()/2, vals.end()); return *(vals.begin()+vals.size()/2); }; std::vector<double> z(view->size()); for (PointId j = 0; j < view->size(); ++j) z[j] = view->getFieldAs<double>(m_dimId, j); double median = estimate_median(z); log()->get(LogLevel::Debug) << getName() << " estimated median value: " << median << std::endl; std::transform(z.begin(), z.end(), z.begin(), [median](double v) { return std::fabs(v - median); }); double mad = estimate_median(z)*m_madMultiplier; log()->get(LogLevel::Debug) << getName() << " mad " << mad << std::endl; for (PointId j = 0; j < view->size(); ++j) { if (z[j]/mad < m_multiplier) output->appendPoint(*view, j); } double low_fence = median - m_multiplier * mad; double hi_fence = median + m_multiplier * mad; log()->get(LogLevel::Debug) << getName() << " cropping " << m_dimName << " in the range (" << low_fence << "," << hi_fence << ")" << std::endl; viewSet.erase(view); viewSet.insert(output); return viewSet; }
PointViewSet RadiusOutlierFilter::run(PointViewPtr input) { bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process RadiusOutlierFilter...\n"; // convert PointView to PointXYZ typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); BOX3D bounds; input->calculateBounds(bounds); pclsupport::PDALtoPCD(input, *cloud, bounds); pclsupport::setLogLevel(log()->getLevel()); // setup the outlier filter pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror(true); ror.setInputCloud(cloud); ror.setMinNeighborsInRadius(m_min_neighbors); ror.setRadiusSearch(m_radius); pcl::PointCloud<pcl::PointXYZ> output; ror.setNegative(true); ror.filter(output); // filtered to return inliers pcl::PointIndicesPtr inliers(new pcl::PointIndices); ror.getRemovedIndices(*inliers); PointViewSet viewSet; if (inliers->indices.empty()) { log()->get(LogLevel::Warning) << "Requested filter would remove all points. Try a larger radius/smaller minimum neighbors.\n"; viewSet.insert(input); return viewSet; } // inverse are the outliers std::vector<int> outliers(input->size()-inliers->indices.size()); for (PointId i = 0, j = 0, k = 0; i < input->size(); ++i) { if (i == (PointId)inliers->indices[j]) { j++; continue; } outliers[k++] = i; } if (!outliers.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Debug2) << "Labeled " << outliers.size() << " outliers as noise!\n"; // set the classification label of outlier returns as 18 // (corresponding to ASPRS LAS specification for high noise) for (const auto& i : outliers) { input->setField(Dimension::Id::Classification, i, 18); } viewSet.insert(input); } if (m_extract) { log()->get(LogLevel::Debug2) << "Extracted " << inliers->indices.size() << " inliers!\n"; // create new PointView containing only outliers PointViewPtr output = input->makeNew(); for (const auto& i : inliers->indices) { output->appendPoint(*input, i); } viewSet.erase(input); viewSet.insert(output); } } else { if (outliers.empty()) log()->get(LogLevel::Warning) << "Filtered cloud has no outliers!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Warning) << "Must choose --classify or --extract\n"; // return the input buffer unchanged viewSet.insert(input); } return viewSet; }
PointViewSet StatisticalOutlierFilter::run(PointViewPtr input) { bool logOutput = log()->getLevel() > LogLevel::Debug1; if (logOutput) log()->floatPrecision(8); log()->get(LogLevel::Debug2) << "Process StatisticalOutlierFilter...\n"; // convert PointView to PointXYZ typedef pcl::PointCloud<pcl::PointXYZ> Cloud; Cloud::Ptr cloud(new Cloud); BOX3D bounds; input->calculateBounds(bounds); pclsupport::PDALtoPCD(input, *cloud, bounds); // PCL should provide console output at similar verbosity level as PDAL int level = log()->getLevel(); switch (level) { case 0: pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS); break; case 1: pcl::console::setVerbosityLevel(pcl::console::L_ERROR); break; case 2: pcl::console::setVerbosityLevel(pcl::console::L_WARN); break; case 3: pcl::console::setVerbosityLevel(pcl::console::L_INFO); break; case 4: pcl::console::setVerbosityLevel(pcl::console::L_DEBUG); break; default: pcl::console::setVerbosityLevel(pcl::console::L_VERBOSE); break; } // setup the outlier filter pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor(true); sor.setInputCloud(cloud); sor.setMeanK(m_meanK); sor.setStddevMulThresh(m_multiplier); pcl::PointCloud<pcl::PointXYZ> output; sor.setNegative(true); sor.filter(output); // filtered to return inliers pcl::PointIndicesPtr inliers(new pcl::PointIndices); sor.getRemovedIndices(*inliers); log()->get(LogLevel::Debug2) << inliers->indices.size() << std::endl; PointViewSet viewSet; if (inliers->indices.empty()) { log()->get(LogLevel::Warning) << "Requested filter would remove all points. Try increasing the multiplier.\n"; viewSet.insert(input); return viewSet; } // inverse are the outliers std::vector<int> outliers(input->size()-inliers->indices.size()); for (PointId i = 0, j = 0, k = 0; i < input->size(); ++i) { if (i == (PointId)inliers->indices[j]) { j++; continue; } outliers[k++] = i; } if (!outliers.empty() && (m_classify || m_extract)) { if (m_classify) { log()->get(LogLevel::Debug2) << "Labeled " << outliers.size() << " outliers as noise!\n"; // set the classification label of outlier returns as 18 // (corresponding to ASPRS LAS specification for high noise) for (const auto& i : outliers) { input->setField(Dimension::Id::Classification, i, 18); } viewSet.insert(input); } if (m_extract) { log()->get(LogLevel::Debug2) << "Extracted " << inliers->indices.size() << " inliers!\n"; // create new PointView containing only outliers PointViewPtr output = input->makeNew(); for (const auto& i : inliers->indices) { output->appendPoint(*input, i); } viewSet.erase(input); viewSet.insert(output); } } else { if (outliers.empty()) log()->get(LogLevel::Warning) << "Filtered cloud has no outliers!\n"; if (!(m_classify || m_extract)) log()->get(LogLevel::Warning) << "Must choose --classify or --extract\n"; // return the input buffer unchanged viewSet.insert(input); } return viewSet; }