上海整站優(yōu)化公司網(wǎng)絡營銷理論
RANSAC原理:略。
其他博客大多都是介紹擬合單條直線或平面的代碼案例,本文介紹如何擬合多條直線或平面,其實是在單個擬合的基礎上接著擬合,以此類推。
注意:步驟中的直線模型是每次隨機在點云中取點計算的。
步驟:
1.根據(jù)所設參數(shù)(點到直線模型的最大距離)把點云分為了內(nèi)點和外點,對內(nèi)點進行直線擬合,得到第一次擬合的直線;
2.提取上一步的外點,按照步驟1再次進行內(nèi)點和外點的劃分,對內(nèi)點擬合直線,得到第二次擬合的直線,并將直線點云疊加到步驟1得到的直線點云中;
3.設置循環(huán)終止的條件,重復步驟1-2,最終擬合出點云中所有直線。
多平面擬合的思想如出一轍,概不贅述。
1.RANSAC擬合點云所有直線
//RANSAC擬合多條直線
pcl::PointCloud<pcl::PointXYZ>::Ptr LineFitting(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {//內(nèi)點點云合并pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_lines(new pcl::PointCloud<pcl::PointXYZ>());while (cloud->size() > 20)//循環(huán)條件{pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr model_line(new pcl::SampleConsensusModelLine<pcl::PointXYZ>(cloud));pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_line);ransac.setDistanceThreshold(0.05); //內(nèi)點到模型的最大距離ransac.setMaxIterations(100); //最大迭代次數(shù)ransac.computeModel(); //直線擬合//根據(jù)索引提取內(nèi)點std::vector<int> inliers;ransac.getInliers(inliers);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_line(new pcl::PointCloud<pcl::PointXYZ>());pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *cloud_line);//若內(nèi)點尺寸過小,不用繼續(xù)擬合,跳出循環(huán)if (cloud_line->width * cloud_line->height < 20) {break;}*cloud_lines = *cloud_lines + *cloud_line;//pcl::io::savePCDFile(path1+ strcount +"_"+ str + ".pcd", *cloud_line);//提取外點pcl::PointCloud<pcl::PointXYZ>::Ptr outliers(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointIndices::Ptr inliersPtr(new pcl::PointIndices);inliersPtr->indices = inliers;pcl::ExtractIndices<pcl::PointXYZ> extract;extract.setInputCloud(cloud);extract.setIndices(inliersPtr);extract.setNegative(true); // 設置為true表示提取外點extract.filter(*outliers);//pcl::io::savePCDFile("C:/pclpoint/data/cp1_lineout"+str+".pcd", *outliers);//cout << outliers->size() << endl;cloud->clear();*cloud = *outliers;}return cloud_lines;
}
2.RANSAC擬合點云所有平面
pcl::PointCloud<pcl::PointXYZ>::Ptr planeFitting(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {//內(nèi)點點云合并pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_planes(new pcl::PointCloud<pcl::PointXYZ>());while (cloud->size() > 100)//循環(huán)條件{//--------------------------RANSAC擬合平面--------------------------pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr model_plane(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud));pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_plane);ransac.setDistanceThreshold(0.01); //設置距離閾值,與平面距離小于0.1的點作為內(nèi)點//ransac.setMaxIterations(100); //最大迭代次數(shù)ransac.computeModel(); //執(zhí)行模型估計//-------------------------根據(jù)索引提取內(nèi)點--------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);std::vector<int> inplanes; //存儲內(nèi)點索引的容器ransac.getInliers(inplanes); //提取內(nèi)點索引pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inplanes, *cloud_plane);//若內(nèi)點尺寸過小,不用繼續(xù)擬合,跳出循環(huán)if (cloud_plane->width * cloud_plane->height < 100) {break;}*cloud_planes = *cloud_planes + *cloud_plane;//提取外點pcl::PointCloud<pcl::PointXYZ>::Ptr outplanes(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointIndices::Ptr inplanePtr(new pcl::PointIndices);inplanePtr->indices = inplanes;pcl::ExtractIndices<pcl::PointXYZ> extract;extract.setInputCloud(cloud);extract.setIndices(inplanePtr);extract.setNegative(true); // 設置為true表示提取外點extract.filter(*outplanes);//pcl::io::savePCDFile("C:/pclpoint/data/cp1_lineout"+str+".pcd", *outliers);//cout << outliers->size() << endl;cloud->clear();*cloud = *outplanes;}//----------------------------輸出模型參數(shù)---------------------------/* Eigen::VectorXf coefficient;ransac.getModelCoefficients(coefficient);cout << "平面方程為:\n" << coefficient[0] << "x + " << coefficient[1] << "y + " << coefficient[2] << "z + "<< coefficient[3] << " = 0" << endl;*///返回最終的擬合結(jié)果點云return cloud_planes;
}