椭圆拟合

看了网上光宇椭圆拟合的各种算法,都差不多,但是写的条理很乱,借鉴别人的成果,修改了下程序,下边是我梳理后的过程。

#include "cv.h"
#include "highgui.h"
int main()
{   //定义图像
IplImage *img3 = cvLoadImage("spot.JPG",0);
IplImage *img2 = cvCloneImage(img3);
//将原图img3阈值化为img2;
cvThreshold(img3, img2, 50, 255, CV_THRESH_BINARY);
IplImage *img4 = cvCloneImage(img3);
cvNamedWindow("Source", 1);
cvNamedWindow("Result", 1);
cvShowImage("Source", img3);
//设置椭圆拟合用到的几个参数
CvMemStorage *stor = cvCreateMemStorage(0);
CvSeq *cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), stor);
CvBox2D32f *box;
CvPoint *PointArray;
CvPoint2D32f *PointArray2D32f;
    //检索椭圆的轮廓,存储在stor
cvFindContours(img2, stor, &cont, sizeof(CvContour),
CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(0, 0));
//清空图像img2,img4;
cvZero(img2);
cvZero(img4);
//绘制所有轮廓并用椭圆拟合
for (; cont; cont = cont->h_next)
{
int i;
int count = cont->total;//轮廓个数
CvPoint center;
CvSize size;
/*个数必须大于6,这是cvFitEllipse_32f的要求*/
if (count<6)
{
continue;
}
//分配内存给点集
PointArray = (CvPoint *)malloc(count*sizeof(CvPoint));
PointArray2D32f = (CvPoint2D32f*)malloc(count*sizeof(CvPoint2D32f));
//分配内存给椭圆数据
box = (CvBox2D32f *)malloc(sizeof(CvBox2D32f));
//得到点集(这个方法值得借鉴)
cvCvtSeqToArray(cont, PointArray, CV_WHOLE_SEQ);
//将CvPoint点集转化为CvBox2D32f集合
for (i = 0; i<count; i++)
{
PointArray2D32f[i].x = (float)PointArray[i].x;
PointArray2D32f[i].y = (float)PointArray[i].y;
}
//拟合当前轮廓
cvFitEllipse(PointArray2D32f, count, box);
//绘制当前轮廓
cvDrawContours(img4, cont, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255),
0, 1, 8, cvPoint(0, 0));
//将椭圆数据从浮点转化为整数表示
center.x = cvRound(box->center.x);
center.y = cvRound(box->center.y);
size.width = cvRound(box->size.width*0.5);
size.height = cvRound(box->size.height*0.5);
box->angle = -box->angle;
//画椭圆
cvEllipse(img4, center, size, box->angle, 0, 360, CV_RGB(0, 0, 255), 1, CV_AA, 0);
free(PointArray);
free(PointArray2D32f);
free(box);
}
cvShowImage("Result", img4);
cvWaitKey(0);
cvSaveImage("1.JPG", img4);
cvReleaseImage(&img2);
cvReleaseImage(&img3);
cvDestroyWindow("Source");
cvDestroyWindow("Result");
return 0;
}




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCL(Point Cloud Library)是一个开源的点云处理库,提供了丰富的点云处理算法和工具。其中,拟合自由曲面是PCL中的一个重要功能之一。 在PCL中,可以使用RANSACRandom Sample Consensus)算法来拟合自由曲面。RANSAC是一种迭代的拟合算法,它通过随机采样一组数据点来估计模型参数,并根据模型与数据点之间的误差进行评估和更新。通过多次迭代,RANSAC可以找到最佳的模型参数。 对于拟合自由曲面,可以使用PCL中的`pcl::SACSegmentation`类来实现。该类提供了拟合平面、球体、圆柱体等几何形状的功能。在拟合自由曲面时,可以选择使用`pcl::SACMODEL_NORMAL_PLANE`模型来表示自由曲面,并设置相应的参数,如最小采样距离、最大迭代次数等。 以下是使用PCL拟合自由曲面的示例代码: ```cpp #include <pcl/point_types.h> #include <pcl/features/normal_3d.h> #include <pcl/segmentation/sac_segmentation.h> // 创建点云对象 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 假设已经从某处获取到了点云数据,并将其存储在cloud中 // 创建法线估计对象 pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud); // 创建KdTree对象,用于法线估计的搜索 pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); ne.setSearchMethod(tree); // 计算法线 pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>); ne.setKSearch(10); // 设置K近邻搜索的数量 ne.compute(*cloud_normals); // 创建分割对象 pcl::SACSegmentation<pcl::PointXYZ> seg; seg.setInputCloud(cloud); seg.setInputNormals(cloud_normals); // 设置模型类型为平面拟合 seg.setModelType(pcl::SACMODEL_NORMAL_PLANE); // 设置方法为RANSAC seg.setMethodType(pcl::SAC_RANSAC); // 设置最大迭代次数 seg.setMaxIterations(1000); // 设置距离阈值 seg.setDistanceThreshold(0.01); // 执行分割 pcl::PointIndices::Ptr inliers(new pcl::PointIndices); pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); seg.segment(*inliers, *coefficients); // 输出拟合结果 std::cout << "Model coefficients: " << coefficients->values << " " << coefficients->values << " " << coefficients->values << " " << coefficients->values << std::endl; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值