边缘检测(下)

上一节写的几种方法无法将轮廓表示出来,只能找到轮廓的位置。轮廓可以理解为一系列的点。在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
      );

你可能感兴趣的:(边缘检测(下))