上海整站優(yōu)化公司網(wǎng)絡(luò)營(yíng)銷理論
RANSAC原理:略。
其他博客大多都是介紹擬合單條直線或平面的代碼案例,本文介紹如何擬合多條直線或平面,其實(shí)是在單個(gè)擬合的基礎(chǔ)上接著擬合,以此類推。
注意:步驟中的直線模型是每次隨機(jī)在點(diǎn)云中取點(diǎn)計(jì)算的。
步驟:
1.根據(jù)所設(shè)參數(shù)(點(diǎn)到直線模型的最大距離)把點(diǎn)云分為了內(nèi)點(diǎn)和外點(diǎn),對(duì)內(nèi)點(diǎn)進(jìn)行直線擬合,得到第一次擬合的直線;
2.提取上一步的外點(diǎn),按照步驟1再次進(jìn)行內(nèi)點(diǎn)和外點(diǎn)的劃分,對(duì)內(nèi)點(diǎn)擬合直線,得到第二次擬合的直線,并將直線點(diǎn)云疊加到步驟1得到的直線點(diǎn)云中;
3.設(shè)置循環(huán)終止的條件,重復(fù)步驟1-2,最終擬合出點(diǎn)云中所有直線。
多平面擬合的思想如出一轍,概不贅述。
1.RANSAC擬合點(diǎn)云所有直線
//RANSAC擬合多條直線
pcl::PointCloud<pcl::PointXYZ>::Ptr LineFitting(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {//內(nèi)點(diǎn)點(diǎn)云合并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)點(diǎn)到模型的最大距離ransac.setMaxIterations(100); //最大迭代次數(shù)ransac.computeModel(); //直線擬合//根據(jù)索引提取內(nèi)點(diǎn)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)點(diǎn)尺寸過小,不用繼續(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);//提取外點(diǎn)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); // 設(shè)置為true表示提取外點(diǎn)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擬合點(diǎn)云所有平面
pcl::PointCloud<pcl::PointXYZ>::Ptr planeFitting(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {//內(nèi)點(diǎn)點(diǎn)云合并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); //設(shè)置距離閾值,與平面距離小于0.1的點(diǎn)作為內(nèi)點(diǎn)//ransac.setMaxIterations(100); //最大迭代次數(shù)ransac.computeModel(); //執(zhí)行模型估計(jì)//-------------------------根據(jù)索引提取內(nèi)點(diǎn)--------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);std::vector<int> inplanes; //存儲(chǔ)內(nèi)點(diǎn)索引的容器ransac.getInliers(inplanes); //提取內(nèi)點(diǎn)索引pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inplanes, *cloud_plane);//若內(nèi)點(diǎn)尺寸過小,不用繼續(xù)擬合,跳出循環(huán)if (cloud_plane->width * cloud_plane->height < 100) {break;}*cloud_planes = *cloud_planes + *cloud_plane;//提取外點(diǎn)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); // 設(shè)置為true表示提取外點(diǎn)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é)果點(diǎn)云return cloud_planes;
}