PCL Halcon用平面切点云(一)

前言

分别使用pcl和halcon 实现用平面来切点云,生成一段轮廓。

一、PCL实现

思路:

设计一个平面,遍历点云中的每个点,计算点云到这个平面的距离,如果再设定的范围内那么保存起来,如果不在那么就继续,然后用体素滤波取点一些砸点,最后用投影来拿到点云轮廓。

步骤:

1、计算点云到平面的距离,保存新的点云


// 用平面切割点云得到轮廓点云
int  PlaneCutingPointCloud(CG_Plane &plane, pcl::PointCloud<pcl::PointXYZRGB>::Ptr   cloud_in, float distance,pcl::PointCloud<pcl::PointXYZRGB>::Ptr  cloud_out)
{
	if (cloud_in->size()<3)
	{
		return  -1;
	}
	float  s = sqrt(pow(plane.A, 2) + pow(plane.B, 2) + pow(plane.C, 2));
	if (s==0) {
		return -1;
	}
	//  遍历点云
	pcl::PointXYZRGB  point;
	for (size_t i = 0; i < cloud_in->size(); i++)
	{
		float  x= cloud_in->points[i].x;
		float  y= cloud_in->points[i].y;
		float  z = cloud_in->points[i].z;

          // 计算距离
		float d =abs( (plane.A*x + plane.B*y + plane.C*z + plane.D) / s);
		if (d<= distance)
		{
			point.x =x;
			point.y = y;
			point.z = z;
			point.r  = cloud_in->points[i].r;
			point.g = cloud_in->points[i].g;
			point.b = cloud_in->points[i].b;
			cloud_out->push_back(point);
		}
	}

	return 0;
}

2、体素滤波


	pcl::PointCloud<pcl::PointXYZRGB> ::Ptr   cloud3(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::VoxelGrid<pcl::PointXYZRGB> v;
	v.setInputCloud(cloud);
	v.setLeafSize(0.01f, 0.01f, 0.01f);
	v.filter(*cloud3);

3、投影到平面


	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZRGB>);

	// 使用一个平面模型ax + by + cz + d = 0,其中a,b,c,d为平面参数
	// 分别对应下面四个通道,比如a = b =1,c = d=0,方程为x=-y,意味着投影在x=-y的平面上。
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);
	coefficients->values[0] = plane.A;
	coefficients->values[1] = plane.B;
	coefficients->values[2] = plane.C;
	coefficients->values[3] = plane.D;

	// ------------------------------投影到平面---------------------------------------
	pcl::ProjectInliers<pcl::PointXYZRGB> proj;
	proj.setModelType(pcl::SACMODEL_PLANE);   //创建投影类型,投影到平面上
	proj.setInputCloud(cloud2);
	proj.setModelCoefficients(coefficients);
	proj.filter(*cloud_projected);

	std::string filename_result22 = "C:\\Users\\Albert\\Desktop\\ContourProject.pcd";
	pcl::io::savePCDFileBinaryCompressed(filename_result22, *cloud_projected);

调用:


// 计算平面切点云的轮廓点云
int  CalcPlaneCutingPointCloud()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("C:\\Users\\Albert\\Desktop\\Mydreamcars.pcd", *cloud_src) == -1)
	{
		cout << "找不到点云,请重新加载!!!" << endl;
		return  -1;
	}
	cout << " 点云的原始个数:      " << cloud_src->size() << endl;
	pcl::PointCloud<pcl::PointXYZRGB> ::Ptr   cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointXYZRGB  point;
	for (size_t i = 0; i < cloud_src->size(); i++)
	{
		point.x = cloud_src->points[i].x;
		point.y = cloud_src->points[i].y;
		point.z = cloud_src->points[i].z;
		point.r = 255;
		point.g = 255;
		point.b = 255;
		cloud->push_back(point);
	}

	Eigen::Vector4f centroid;
	pcl::compute3DCentroid(*cloud, centroid);

	cout << " 点云的原始个数2:      " << cloud->size() << endl;
	if (cloud->size()<3)
	{
		return  -1;
	}


	pcl::PointCloud<pcl::PointXYZRGB> ::Ptr   cloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
	CG_Plane  plane ;
	plane.A = 1;
	plane.B = 1;
	plane.C = 1;
	plane.D = -(plane.A*centroid[0] + plane.B*centroid[1] + plane.C*centroid[2]);

	pcl::PointCloud<pcl::PointXYZRGB> ::Ptr   cloud3(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::VoxelGrid<pcl::PointXYZRGB> v;
	v.setInputCloud(cloud);
	v.setLeafSize(0.01f, 0.01f, 0.01f);
	v.filter(*cloud3);

	std::string filename_result22333 = "C:\\Users\\Albert\\Desktop\\Filter.pcd";
	pcl::io::savePCDFileBinaryCompressed(filename_result22333, *cloud3);

	PlaneCutingPointCloud(plane, cloud3,0.006f, cloud2);
	if (cloud2->size()<3)
	{
		return -1;
	}
	std::string filename_result = "C:\\Users\\Albert\\Desktop\\Contour.pcd";
	pcl::io::savePCDFileBinaryCompressed(filename_result, *cloud2);


	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZRGB>);

	// 使用一个平面模型ax + by + cz + d = 0,其中a,b,c,d为平面参数
	// 分别对应下面四个通道,比如a = b =1,c = d=0,方程为x=-y,意味着投影在x=-y的平面上。
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);
	coefficients->values[0] = plane.A;
	coefficients->values[1] = plane.B;
	coefficients->values[2] = plane.C;
	coefficients->values[3] = plane.D;

	// ------------------------------投影到平面---------------------------------------
	pcl::ProjectInliers<pcl::PointXYZRGB> proj;
	proj.setModelType(pcl::SACMODEL_PLANE);   //创建投影类型,投影到平面上
	proj.setInputCloud(cloud2);
	proj.setModelCoefficients(coefficients);
	proj.filter(*cloud_projected);

	std::string filename_result22 = "C:\\Users\\Albert\\Desktop\\ContourProject.pcd";
	pcl::io::savePCDFileBinaryCompressed(filename_result22, *cloud_projected);
	return 0;
}

 CC技巧:将mesh 的模型转换成点云

cc下采样:

 

 二、Halcon 实现

halcon案例

intersect_plane_object_model_3d.hdev

 Halcon 代码:

* ********************************************************************
* This program shows how to calculate the intersection between a
* 3D object model and a plane.
* The intersection is calculated with the operator
* intersect_plane_object_model.
* The result of the intersection is a set of polylines.
* ********************************************************************
* 
* Read 3D object model
Files := ['bmc_mini','glass_mug']
* 
* Prepare visualization
dev_update_off ()
dev_close_window ()
* 
gen_cam_par_area_scan_division (0.01, 0, 7e-6, 7e-6, 240, 180, 480, 360, CamParam)
get_cam_par_data (CamParam, 'image_width', ImageWidth)
get_cam_par_data (CamParam, 'image_height', ImageHeight)
dev_open_window (0, 0, ImageWidth, ImageHeight, 'black', WindowHandle1)
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
dev_open_window (0, ImageWidth + 12, ImageWidth, ImageHeight, 'black', WindowHandle2)
set_display_font (WindowHandle2, 14, 'mono', 'true', 'false')
* Poses for car object
create_pose (0.05, 0.10, 1.2, 181.4, 30.6, 359.0, 'Rp+T', 'gba', 'point', VisualizationPose)
create_pose (0.12, 0.08, 1.2, 180.0, 90.0, 0.0, 'Rp+T', 'gba', 'point', PoseConnected)
create_pose (0, 0, 0, 0, 90, 0, 'Rp+T', 'gba', 'point', CutPlanePose)
Border := 0.03
* Poses for mug object
VisualizationPose := [VisualizationPose,6.5e-005,-0.15e-3,8.1e-3,120.0,0.0,30.0,0]
CutPlanePose := [CutPlanePose,0,0,0,70,0,0,0]
PoseConnected := [PoseConnected,0.0,-0.1e-3,6.0e-3,90.0,0.0,0.0,0]
Border := [Border,0.0003]
* 
GenParamName := ['color_0','attribute_0','disp_pose_0','light_position']
GenParamValue := ['green','faces','true','0.0 0.0 100.0 1.0']
GenParamName := [GenParamName,'color_1','disp_pose_1','alpha']
GenParamValue := [GenParamValue,'red','false',.5]
ColorSytle := ['colored','color']
ColorValue := [12,'green']
* 
* Compute the interection of a 3d object model with a plane
* successively with two different Object models.
for Index := 0 to |Files| - 1 by 1
    * 
    * Read a 3d object model
    read_object_model_3d (Files[Index], 'mm', [], [], ObjectModel3D, Status)
    * 
    * Compute the intersection of the object with the plane
    * and calculate the connected components.
    CurrentCutPlanePose := CutPlanePose[Index * 7:Index * 7 + 6]
    count_seconds (Seconds)
    triangulate_object_model_3d (ObjectModel3D, 'greedy', [], [], TriangulatedObjectModel3D, Information)
    intersect_plane_object_model_3d (ObjectModel3D, CurrentCutPlanePose, ObjectModel3DIntersection)
    count_seconds (Seconds1)
    stop ()
    connection_object_model_3d (ObjectModel3DIntersection, 'lines', 1, ObjectModel3DConnected)
    * 
    * Display results
    * 
    * Calculate plane extents for visualization
    pose_invert (CurrentCutPlanePose, PoseInvert)
    rigid_trans_object_model_3d (ObjectModel3DIntersection, PoseInvert, ObjectModel3DRigidTrans)
    * 
    get_object_model_3d_params (ObjectModel3DRigidTrans, 'bounding_box1', Param1)
    X := [Param1[0] - Border[Index],Param1[0] - Border[Index],Param1[3] + Border[Index],Param1[3] + Border[Index]]
    Y := [Param1[1] - Border[Index],Param1[4] + Border[Index],Param1[4] + Border[Index],Param1[1] - Border[Index]]
    * Generate plane to visualize the intersecting plane
    gen_plane_object_model_3d (CurrentCutPlanePose, X, Y, ObjectModel3DPlane)
    * Visualize the scene
    Message := ['Compute the intersection','of the object with the plane']
    disp_object_model_3d_safe (WindowHandle1, [ObjectModel3D,ObjectModel3DPlane], CamParam, VisualizationPose[Index * 7:Index * 7 + 6], GenParamName, GenParamValue)
    disp_message (WindowHandle1, Message, 'window', 12, 12, 'white', 'false')
    * Display the intersection of the object with the plane
    get_object_model_3d_params (ObjectModel3DIntersection, 'num_points', NumPoints)
    if (NumPoints > 0)
        disp_object_model_3d_safe (WindowHandle2, ObjectModel3DConnected, CamParam, PoseConnected[Index * 7:Index * 7 + 6], ['disp_lines',ColorSytle[Index]], ['true',ColorValue[Index]])
        disp_message (WindowHandle2, 'Runtime = ' + ((Seconds1 - Seconds) * 1e3)$'.3' + ' ms', 'window', 12, 12, 'white', 'false')
    else
        Message := 'The intersection of the object with the plane is empty!'
        disp_message (WindowHandle1, Message, 'window', 12, 12, 'white', 'false')
    endif
    * 
    * It is also possible to project the resulting 3D lines into the
    * intersection plane and to convert these planar lines into XLD
    * contours.
    project_object_model_3d_lines_to_contour_xld (Intersection, CurrentCutPlanePose, ObjectModel3DIntersection)
    * Depending on the scale and position of the 3D object, a
    * transformation of the contours might be required for a suitable
    * visualization. The transformation parameters are determinde based
    * on the extent of the intersection contours.
    determine_transformation_parameters (Intersection, ImageHeight, ImageWidth, 0.1, HomMat2D)
    affine_trans_contour_xld (Intersection, ContoursAffineTrans, HomMat2D)
    * 
    if (Index < |Files| - 1)
        disp_continue_message (WindowHandle2, 'black', 'true')
        stop ()
    endif
endfor

猜你喜欢

转载自blog.csdn.net/weixin_39354845/article/details/131066356