上一节写的几种方法无法将轮廓表示出来,只能找到轮廓的位置。轮廓可以理解为一系列的点。在OpenCV中,轮廓一般用序列来存储。
查找轮廓
OpenCV中查找轮廓使用cvFindContours()函数。可以将图像用cvCanny()函数或是cvThreshold()函数处理后调用cvFindContours()函数。
int cvFindContours(
IplImage * img,
CvMemStorage * storage,
CvSeq ** firstContour,
int headerSize = sizeof(CvContour),
CvContourRetrievalMode mode = CV_RETR_LIST,
CvChainApproxMethod method = CV_CHAIN_APPROX_SIMPLE
);
第一个参数是输入图像,图像必须要8为单通道图像,并且应该被转化成二值。第二个参数是内存存储器,接着是指向CvSeq的指针,函数会自动分配,后面则是函数的一些设置。
Freeman链码
一般情况下通过cvFindContours()函数获得的是一系列顶点的序列。另一种不同的表达是设置method参数为CV_CHAIN_CODE,然后生成轮廓,通过Freeman链码方式返回。Freeman链码在每个点上提供八个方向向量,以表示下一个点的位置。可以通过cvStartReadChainPoints()或cvReadChainPoint()函数来读出每个点。
多边形逼近
当我们绘制一个多边形或者进行形状分析的时候,通常需要使用多边形逼近一个轮廓,使得定点数目尽可能少。函数cvApproxPoly()是一种实现。首先在轮廓里选择两个距离最远的点,将这两点连在一起,查找距离这条线段最远的点,将该点加入,并不断的找距离最远的点,如此迭代。
CvSeq * cvApproxPoly(
const void * src_seq,
int header_size,
CvMemstorage * storage,
int method,
double parameter,
int recursive = 0
);
轮廓的匹配
比较轮廓最简单的方法是比较轮廓的矩。矩是通过对轮廓上所有的点进行积分运算而得到的一个粗略特征。OpenCV用cvContoursMoments()函数计算矩
void cvContoursMoments(
CvSeq * contour,
CvMoments * moments
);
第一个参数指向要处理的轮廓,第二个参数指向的结构保存生成的结果。
访问矩的结果使用CvMoments()函数
double cvGetSpatialMoment(
CvMoments * moments,
int x_order,
int y_order
);
矩计算给出了一些轮廓的简单属性可以用来比较两个轮廓,但是很多情况下这些并不是最好的参数,更多用到的事归一化的矩。OpenCV提供了计算Hu不变矩和其他归一化矩的函数。具体是cvMoments(),cvGetCentralMoment(),cvGetNormalizedCentralMoment(),cvGetHuMoments()。具体用法这里不列出来了。同时也提供了cvMatchShapes()函数进行Hu矩匹配。
double cvMatchShapes(
const void * object1,
const void * object2,
int method,
double parameter
);
网友评论