PCL笔记六:点云滤波;复用配置PCL环境;

需要滤波:

  • 噪声点
  • 离散点
  • 空洞

滤波处理算法:

  • 双边滤波
  • 高斯滤波
  • 条件滤波
  • 直通滤波
  • 基于随机采样一致性滤波

二次配置PCL环境如何简便操作:

在笔记一中:PCL笔记一:Windows10安装PCL;与VS2019联合调试;保存点云为PCD文档

我们对如何在vs中配置PCL进行了讲解。当我们需要重新开辟一个项目时,如何简单易行呢?

在VS中新建一个项目:比如02 滤波

 打开属性管理器:对比两个项目:我们发现:新项目缺少PCL的配置

 如果想复用上一个项目中的配置

 把这个文件复制到我们的新项目目录下:我们当时的命名是PCL1.12.0X64

 

 

 

 至此配置完成。同一个电脑最简单有效,如果换一台电脑,要注意按照笔记一种方法添加配置。


直通滤波器对点云滤波

#include <iostream>
#include <ctime>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>


int
main(int argc, char** argv)
{
    srand(time(0));
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
    //填入点云数据
    cloud->width = 5;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i].x = rand() / (RAND_MAX + 1.0f) - 0.5;
        cloud->points[i].y = rand() / (RAND_MAX + 1.0f) - 0.5;
        cloud->points[i].z = rand() / (RAND_MAX + 1.0f) - 0.5;
    }
    std::cerr << "Cloud before filtering: " << std::endl;
    for (size_t i = 0; i < cloud->points.size(); ++i)
        std::cerr << "    " << cloud->points[i].x << " "
        << cloud->points[i].y << " "
        << cloud->points[i].z << std::endl;


    // 创建滤波器对象
    pcl::PassThrough<pcl::PointXYZ> pass;   // 滤波器对象。
    pass.setInputCloud(cloud);  // 设置输入点云
    pass.setFilterFieldName("z");  // 过滤限定范围z字段轴。
    pass.setFilterLimits(0.0, 1.0);  // 过滤字段范围。
    //pass.setFilterLimitsNegative (true);  // 保留还是舍弃。true:符合条件保留。
    pass.filter(*cloud_filtered);   // 执行滤波,保存在cloud_filtered指针。

    std::cerr << "Cloud after filtering: " << std::endl;
    for (size_t i = 0; i < cloud_filtered->points.size(); ++i)
        std::cerr << "    " << cloud_filtered->points[i].x << " "
        << cloud_filtered->points[i].y << " "
        << cloud_filtered->points[i].z << std::endl;
    return (0);
}

输出: 

Cloud before filtering:
    -0.0175171 -0.0680542 -0.306366
    0.367126 -0.394836 0.212524
    -0.36554 -0.488831 0.329926
    0.397644 -0.489227 0.0578308
    -0.248871 0.187042 0.274689
Cloud after filtering:
    0.367126 -0.394836 0.212524
    -0.36554 -0.488831 0.329926
    0.397644 -0.489227 0.0578308
    -0.248871 0.187042 0.274689

虽然是完成了。过滤,但是。这个程序会在程序执行完报错。目前想到的解决方案是try



使用VoxelGrid滤波器对点云进行下采样

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/PCLPointCloud2.h>


int
main(int argc, char** argv)
{
    pcl::PCLPointCloud2::Ptr cloud(new pcl::PCLPointCloud2());
    pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2());
    // 填入点云数据
    pcl::PCDReader reader;
    // 把路径改为自己存放文件的路径
    reader.read("C:\\Users\\1987wangsanguo\\Desktop\\PCD_Viewer\\PCD_Viewer\\2f_only_voxel.pcd", *cloud); 
    // 记住要事先下载这个数据集!
    std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
        << " data points (" << pcl::getFieldsList(*cloud) << ").";
    // 创建滤波器对象
    pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
    sor.setInputCloud(cloud);
    sor.setLeafSize(0.01f, 0.01f, 0.01f);   // 设置滤波时创建的体素大小为1cm立方体。
    sor.filter(*cloud_filtered);
    std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
        << " data points (" << pcl::getFieldsList(*cloud_filtered) << ").";
    pcl::PCDWriter writer;
    writer.write("2f.pcd", *cloud_filtered,
        Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), false);
    return (0);
}

StatisticalOutlierRemoval滤波器移除离散点

使用统计分析技术,从点云集中移除测量噪声点(离群点)。

对每个点的领域进行一个统计分析,并修剪掉那些不符合一定标准的点。

稀疏离群点移除方法基于在输入数据中对点到临近点的距离分布的计算。

对每个点,我们计算他到他的所有临近点平均距离。假设得到的结果是一个高斯分布,其形状由均值和标准差决定,平均距离在标准范围(由全局距离平均值和方差定义)之外的点,可被定义为离群点并可从数据集中去除掉。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
int
main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
	// 填入点云数据
	pcl::PCDReader reader;
	// 把路径改为自己存放文件的路径
	reader.read<pcl::PointXYZ>("table_scene_lms400.pcd", *cloud);
	std::cerr << "Cloud before filtering: " << std::endl;
	std::cerr << *cloud << std::endl;
	// 创建滤波器对象
	pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
	sor.setInputCloud(cloud);
	sor.setMeanK(50);
	sor.setStddevMulThresh(1.0);
	sor.filter(*cloud_filtered);
	std::cerr << "Cloud after filtering: " << std::endl;
	std::cerr << *cloud_filtered << std::endl;
	pcl::PCDWriter writer;
	writer.write<pcl::PointXYZ>("table_scene_lms400_inliers.pcd", *cloud_filtered, false);
	sor.setNegative(true);    // 设置时输出取外点,获取离群点数据。
	sor.filter(*cloud_filtered);
	writer.write<pcl::PointXYZ>("table_scene_lms400_outliers.pcd", *cloud_filtered, false);
	return (0);
}


参数化模型投影点云

将点投影到一个参数化模型上(例如平面或者球)。PCL中有特意存储常见模型系数的数据结构。

例如平面:使用其等式:ax + by + cz + d = 0。如果我们构造X-Y平面:a= b =d =0;c=1即可。

这个平面模型应用场景广泛。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/project_inliers.h>
int
main(int argc, char** argv)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);
    // 填入点云数据
    cloud->width = 5;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }
    std::cerr << "Cloud before projection: " << std::endl;
    for (size_t i = 0; i < cloud->points.size(); ++i)
        std::cerr << "    " << cloud->points[i].x << " "
        << cloud->points[i].y << " "
        << cloud->points[i].z << std::endl;
    // 创建一个系数为X=Y=0,Z=1的平面;单词:Coefficients:系数
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    coefficients->values.resize(4);
    coefficients->values[0] = coefficients->values[1] = 0;
    coefficients->values[2] = 1.0;
    coefficients->values[3] = 0;
    // 创建滤波器对象
    pcl::ProjectInliers<pcl::PointXYZ> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(cloud);
    proj.setModelCoefficients(coefficients);
    proj.filter(*cloud_projected);

    std::cerr << "Cloud after projection: " << std::endl;
    for (size_t i = 0; i < cloud_projected->points.size(); ++i)
        std::cerr << "    " << cloud_projected->points[i].x << " "
        << cloud_projected->points[i].y << " "
        << cloud_projected->points[i].z << std::endl;

    return (0);
}

输出:

Cloud before projection:
    1.28125 577.094 197.938
    828.125 599.031 491.375
    358.688 917.438 842.563
    764.5 178.281 879.531
    727.531 525.844 311.281
Cloud after projection:
    1.28125 577.094 0
    828.125 599.031 0
    358.688 917.438 0
    764.5 178.281 0
    727.531 525.844 0

xy没有变化。但是z都变成了0



点云集中提取点云子集

先使用VoxelGrid滤波器对数据进行下采样,下采样的目的是:为了加速处理过程。越少的点意味着分割循环中处理器起来越快。

#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/PCLPointCloud2.h>


int
main(int argc, char** argv)
{
    pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2), cloud_filtered_blob(new pcl::PCLPointCloud2);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>), cloud_p(new pcl::PointCloud<pcl::PointXYZ>), cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
    // 填入点云数据
    pcl::PCDReader reader;
    reader.read("table_scene_lms400.pcd", *cloud_blob);
    std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;
    // 创建滤波器对象:使用叶大小为1cm的下采样。
    pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
    sor.setInputCloud(cloud_blob);
    sor.setLeafSize(0.01f, 0.01f, 0.01f);
    sor.filter(*cloud_filtered_blob);
    // 转化为模板点云
    pcl::fromPCLPointCloud2(*cloud_filtered_blob, *cloud_filtered);
    std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;
    // 将下采样后的数据存入磁盘
    pcl::PCDWriter writer;
    writer.write<pcl::PointXYZ>("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
    // 创建分割对象
    pcl::SACSegmentation<pcl::PointXYZ> seg;
    // 可选
    seg.setOptimizeCoefficients(true);
    // 必选
    seg.setModelType(pcl::SACMODEL_PLANE);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setMaxIterations(1000);
    seg.setDistanceThreshold(0.01);
    // 创建滤波器对象
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    int i = 0, nr_points = (int)cloud_filtered->points.size();
    // 当还有30%原始点云数据时
    while (cloud_filtered->points.size() > 0.3 * nr_points)
    {
        // 从余下的点云中分割最大平面组成部分
        seg.setInputCloud(cloud_filtered);
        seg.segment(*inliers, *coefficients);
        if (inliers->indices.size() == 0)
        {
            std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;
            break;
        }
        // 分离内层
        extract.setInputCloud(cloud_filtered);
        extract.setIndices(inliers);
        extract.setNegative(false);
        extract.filter(*cloud_p);
        std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;
        std::stringstream ss;
        ss << "table_scene_lms400_plane_" << i << ".pcd";
        writer.write<pcl::PointXYZ>(ss.str(), *cloud_p, false);
        // 创建滤波器对象
        extract.setNegative(true);
        extract.filter(*cloud_f);
        cloud_filtered.swap(cloud_f);
        i++;
    }
    return (0);
}

PointCloud before filtering: 460400 data points.
PointCloud after filtering: 41049 data points.
PointCloud representing the planar component: 20161 data points.
PointCloud representing the planar component: 12114 data points.

关于子集分割应用场景:比较符合规模较大的点云,在使用点云上采样算法时,将大点云分割成小的patch。将patch喂入神经网络中训练或者输出。

关于平面分割应用场景:将平面提取出来,然后与上文中提到的平面模型X-Y平面,做标定,可以完成对安装设备的倾斜标定。假设我们认为扫描地面就是平的



使用ConditionalRemoval或RadiusOutlinerRemoval移除离群点

在滤波器模块中使用几种不同的方法移除离群点。

  • 使用RadiusOutlierRemoval滤波器可以删除在一定范围内没有足够多紧邻点的数据点。
  • 使用ConditionalRemoval滤波器可以对输入的点云一次性删除满足多个条件的数据点。

半径d内,设定一定的近邻数目评估指标,如果近邻点数够则留,否则删。

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>


int
main(int argc, char** argv)
{
    if (argc != 2)
    {
        std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
        exit(0);
    }
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
    // 填入点云数据
    cloud->width = 5;
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }
    if (strcmp(argv[1], "-r") == 0) {
        std::cerr << "执行半径滤波:" << std::endl;
        pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
        // 创建滤波器
        outrem.setInputCloud(cloud);
        outrem.setRadiusSearch(700);
        outrem.setMinNeighborsInRadius(2);
        // 应用滤波器
        outrem.filter(*cloud_filtered);
    }
    else if (strcmp(argv[1], "-c") == 0) {
        // 创建环境
        pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());
        range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new            pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 300)));
        range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new            pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 600)));
        // 创建滤波器
        std::cerr << "执行条件滤波:" << std::endl;
        pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
        condrem.setCondition(range_cond);
        condrem.setInputCloud(cloud);
        condrem.setKeepOrganized(true);
        // 应用滤波器
        condrem.filter(*cloud_filtered);
    }
    else {
        std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
        exit(0);
    }
    std::cerr << "Cloud before filtering: " << std::endl;
    for (size_t i = 0; i < cloud->points.size(); ++i)
        std::cerr << "    " << cloud->points[i].x << " "
        << cloud->points[i].y << " "
        << cloud->points[i].z << std::endl;
    // 显示滤波后的点云
    std::cerr << "Cloud after filtering: " << std::endl;
    for (size_t i = 0; i < cloud_filtered->points.size(); ++i)
        std::cerr << "    " << cloud_filtered->points[i].x << " "
        << cloud_filtered->points[i].y << " "
        << cloud_filtered->points[i].z << std::endl;
    return (0);
}

VS中给main函数传入参数的实现方式:

【项目】【属性】【调试】【命令参数】

执行条件滤波:
Cloud before filtering:
    1.28125 577.094 197.938
    828.125 599.031 491.375
    358.688 917.438 842.563
    764.5 178.281 879.531
    727.531 525.844 311.281
Cloud after filtering:
    nan nan nan
    828.125 599.031 491.375
    nan nan nan
    nan nan nan
    727.531 525.844 311.281
执行半径滤波:
Cloud before filtering:
    1.28125 577.094 197.938
    828.125 599.031 491.375
    358.688 917.438 842.563
    764.5 178.281 879.531
    727.531 525.844 311.281
Cloud after filtering:
    828.125 599.031 491.375
    764.5 178.281 879.531
    727.531 525.844 311.281

问题记录保留: 



CropHull任意多边形内部点云提取

凸包convexhull、凹包convexHull检测。ROI截取。

#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <vector>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/surface/convex_hull.h>

int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	// pcd文件读取器
	pcl::PCDReader reader;
	reader.read("pig.pcd", *cloud);

	// 输入2D平面点云。
	pcl::PointCloud<pcl::PointXYZ>::Ptr boundingbox_ptr(new pcl::PointCloud<pcl::PointXYZ>);
	boundingbox_ptr->push_back(pcl::PointXYZ(0.1, 0.1, 0));
	boundingbox_ptr->push_back(pcl::PointXYZ(0.1, -0.1, 0));
	boundingbox_ptr->push_back(pcl::PointXYZ(-0.1, 0.1, 0));
	boundingbox_ptr->push_back(pcl::PointXYZ(-0.1, -0.1, 0));
	boundingbox_ptr->push_back(pcl::PointXYZ(0.15, 0.1, 0));
	
	// 构造2D凸包。
	pcl::ConvexHull<pcl::PointXYZ> hull;  // 实例对象
	hull.setInputCloud(boundingbox_ptr);  // 输入点云
	hull.setDimension(2);                //设置凸包维度。
	std::vector<pcl::Vertices> polygons;  // Vertices向量:顶点向量。至高点。用于保存凸包的顶点向量。
	pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull(new pcl::PointCloud<pcl::PointXYZ>);   //该点运用于描述凸包形状
	hull.reconstruct(*surface_hull, polygons); //计算2D凸包结果,结果保存在suiface_hull中。

	pcl::PointCloud<pcl::PointXYZ>::Ptr objects(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::CropHull<pcl::PointXYZ> bb_filter;  //创建crophull对象
	bb_filter.setDim(2);   //设置维度:该维度需要与凸包维度一致
	bb_filter.setInputCloud(cloud);    //设置需要滤波的点云
	bb_filter.setHullIndices(polygons);   //输入封闭多边形的顶点。顶点向量
	bb_filter.setHullCloud(surface_hull);   //输入封闭多边形的形状
	bb_filter.filter(*objects);       // //执行CropHull滤波,存出结果在objects
	std::cout << objects->size() << std::endl;

	//visualize
	boost::shared_ptr<pcl::visualization::PCLVisualizer> for_visualizer_v(new pcl::visualization::PCLVisualizer("crophull display"));
	for_visualizer_v->setBackgroundColor(255, 255, 255);

	int v1(0);   // 显示原始点云
	for_visualizer_v->createViewPort(0.0, 0.0, 0.33, 1, v1);
	for_visualizer_v->setBackgroundColor(255, 255, 255, v1);
	for_visualizer_v->addPointCloud(cloud, "cloud", v1);
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 255, 0, 0, "cloud");
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
	for_visualizer_v->addPolygon<pcl::PointXYZ>(surface_hull, 0, .069 * 255, 0.2 * 255, "backview_hull_polyline1", v1);

	int v2(0);   //显示封闭2D多边形凸包
	for_visualizer_v->createViewPort(0.33, 0.0, 0.66, 1, v2);
	for_visualizer_v->setBackgroundColor(255, 255, 255, v2);
	for_visualizer_v->addPointCloud(surface_hull, "surface_hull", v2);
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 255, 0, 0, "surface_hull");
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 8, "surface_hull");
	for_visualizer_v->addPolygon<pcl::PointXYZ>(surface_hull, 0, .069 * 255, 0.2 * 255, "backview_hull_polyline", v2);

	int v3(0);    //显示滤波结果
	for_visualizer_v->createViewPort(0.66, 0.0, 1, 1, v3);
	for_visualizer_v->setBackgroundColor(255, 255, 255, v3);
	for_visualizer_v->addPointCloud(objects, "objects", v3);
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 255, 0, 0, "objects");
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "objects");

	while (!for_visualizer_v->wasStopped())
	{

		for_visualizer_v->spinOnce(1000);
	}
	system("pause");
}

输出:



案例分析

第六章末尾作者分享了一个手机外壳全尺寸检测的案例。非常好。

设备:高精度点云采集设备:z轴分辨率50um

  • 开发者已经拥有了被检测对象的结构信息
  • 知道加工模型的尺寸
  • 扫描时系统的工作位置。

充分利用结构信息作为参考,对于自动化高精度的检测很有意义

对于感兴趣区域的提取:思路:

1、使用系统本身的信息和加工模型的尺寸作为参考,大致分割包含需要检测的部位的区域,作为ROI。

2、在ROI基础上进行关键部位的精确定位与检测。

3、结合平面、圆柱、直线、边缘检测等技术定位测量。

检测处理步骤:

1、实物扫描,获取点云图。

2、标定,多手段标定。获取精确位置信息。

3、滤波:去除边缘信息和离群点。

4、结合物料信息粗略定位

5、结合特征信息精确定位

6、业务逻辑处理。

代码中:通过直通滤波切割三个维度的区域。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值