OpenCV入门(二十八) -- 多边形逼近

绘制多边形或者进行形状分析的时候,通常需要使用多边形逼近一个轮廓。

ApproxPoly

用指定精度逼近多边形曲线

CvSeq* cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage,
                     int method, double parameter, int parameter2=0 );
src_seq
点集数组序列
header_size
逼近曲线的头尺寸
storage
逼近轮廓的容器。如果为 NULL, 则使用输入的序列
method
逼近方法。目前仅支持 CV_POLY_APPROX_DP , 对应 Douglas-Peucker 算法.
parameter
方法相关参数。对 CV_POLY_APPROX_DP 它是指定的逼近精度
parameter2
如果 src_seq 是序列,它表示要么逼近单个序列,要么在 src_seq 的同一个或低级层次上逼近所有序列 (参考 cvFindContours 中对轮廓继承结构的描述). 如果 src_seq 是点集的数组 (CvMat*) , 参数指定曲线是闭合 (parameter2!=0) 还是非闭合 (parameter2=0).

函数 cvApproxPoly 逼近一个或多个曲线,并返回逼近结果。对多个曲线的逼近,生成的树将与输入的具有同样的结构。(1:1 的对应关系).


用到的另一个函数的定义是:

#define cvContourPerimeter(contour)

这个函数作用于一个轮廓并返回其长度,事实上,此函数是一个调用通用函数cvArcLength()的宏

ArcLength

计算轮廓周长或曲线长度

double cvArcLength( const void* curve, CvSlice slice=CV_WHOLE_SEQ, int is_closed=-1 );
curve
曲线点集序列或数组
slice
曲线的起始点,缺省是计算整个曲线的长度
is_closed
表示曲线是否闭合,有三种情况:
  • is_closed=0 - 假设曲线不闭合
  • is_closed>0 - 假设曲线闭合
  • is_closed<0 - 若曲线是序列,检查 ((CvSeq*)curve)->flags 中的标识 CV_SEQ_FLAG_CLOSED 来确定曲线是否闭合。否则 (曲线由点集的数组 (CvMat*) 表示) 假设曲线不闭合。

函数 cvArcLength 通过依次计算序列点之间的线段长度,并求和来得到曲线的长度。


函数代码:

/*
* 多边形逼近
*/

#include "highgui.h"
#include "cv.h"

void doApporx(IplImage* img)
{
	IplImage* s =cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	IplImage* dst = cvCreateImage(cvGetSize(img), img->depth, img->nChannels);
	IplImage* dst2 = cvCreateImage(cvGetSize(img), img->depth, img->nChannels);
	cvZero(dst);
	cvZero(dst2);
	CvMemStorage* storage = cvCreateMemStorage(0); 
	CvMemStorage* storage1 = cvCreateMemStorage(0);
	CvSeq* contour = 0;
	CvSeq* con ;
	CvSeq* mcon = NULL;

	cvCvtColor(img, s, CV_BGR2GRAY);
	cvThreshold(s, s, 100, 200, CV_THRESH_BINARY);
	cvFindContours(s,storage,&contour,sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
	// 不使用多边形逼近的轮廓
	cvDrawContours(dst2, contour, CV_RGB(0,0,255), CV_RGB(0,0,255), 2,2,8, cvPoint(0,0));
	cvNamedWindow("cont",1);
	cvShowImage("cont",dst2);

	while(contour != 0)
	{
		// 使用对变形逼近
		mcon = cvApproxPoly(contour, sizeof(CvContour), storage1, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);
		cvDrawContours(dst, mcon, CV_RGB(0,0,255), CV_RGB(0,255,0), 2,2,8,cvPoint(0,0));
		contour = contour->h_next;
	}
	cvNamedWindow("contour",1);
	cvShowImage("contour",dst);
	cvWaitKey(0);
}

显示结果:

原始图像:


结果显示:



参考博客:

http://buaagc.blog.163.com/blog/static/727883942013109145356/

http://blog.csdn.net/augusdi/article/details/9021939

图片来源:

http://blog.csdn.net/augusdi/article/details/9021939

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值