关于求最大联通域的OpenCV方法

来源:互联网 发布:ubuntu 命令行解压deb 编辑:程序博客网 时间:2024/06/14 08:19

     最近一直在实验室编写关于室内独居老人异常行为检测的代码。感觉有点吃力,在网上找了一些代码,然后看到了一个关于求最大连通域的代码,感觉不错,现在在这里讲解一下这个方法涉及到的函数,

cvFindContours

   

该函数的作用是Finds contours in a binary image也就是在一个二值图像中查找连通域,contour(轮廓;外形;(地图上表示相同海拔各点的)等高线描画…的轮廓;画…的等高[等值]线;顺等高线(作业)),也就是连通域的意思。它的函数原型是: void findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode,

                                               int method,   Pointoffset=Point())


     该函数的参数是image-源,一个8位单通道的图像。非零像素按照1对待,0像素仍然是0.所以这个图像按照二值得方式进行对待。我们可以使用compare(), inRange(), threshold(),adaptiveThreshold(), Canny(),和其他的函数来通过一个灰阶图像或者彩色图像创建一个二值图像。当提取轮廓的时候,该函数会调整这幅图像。

countour--被检测的轮廓数量,每一个轮廓保存为一个点向量。mode  --连通域获取模式

--CV_RETR_EXTERNAL, 仅仅检索这个最外轮廓,对于所有的轮廓,它设置hierarchy[i][2]= hierarchy[i][3]=-1

--CV_RETR_TREE获取所有的轮廓,并且重建潜逃轮廓的完整层次。这个完整的层次在openCV contours.c demo中建立和展示。

method--轮廓逼近的方法

--CV_CHAIN_APPROX_NONE 绝对的存储所有的轮廓点,即,任何轮廓中两个连续的点(x1, x2)和(x2, y2)要么水平,垂直,要么是对角的邻居。也就是说(max(abs(x1-x2), abs(y2-y1))==1)

CV_CHAIN_APPROX_SIMPLE压缩水平的,垂直的和对角的部分仅仅留下他们的断点。举个例子,一个上-右的矩形框的轮廓是用四个点编码的。

--CV_CHAIN_APPROX_TC89,CV_CHAIN_TC89_KCOS应用了The-Chin的链式逼近算法口味的一种。如果想要查看细节,请查阅[TehChin89]

offset--可选的偏移量,通过这个点,每个轮廓被移位。如果这个轮廓是从ROI中提取到的花,这个参数是很有用的。并且它们应该在整幅图像环境中进行分析。

总之,这个函数使用Suzuki85算法从二值化的图像中检索轮廓。轮廓是一个有用的工具,对于形状分析和目标检测和识别,在OpenCV的范文目录中查阅squares.c

drawContours

    画出连通域的轮廓或者被填充的轮廓。函数原型是

void cvDrawContours(CvArr* img, CvSeq* contour, CvScalar externalColor, CvScalar holeColor, int maxLevel, intthickness=1, intlineType=8 )

如果thickness>0这个函数画出轮廓的概要或者如果thickness<0填充由contours界定的轮廓。

cvContourArea( contour, CV_WHOLE_SEQ )


 /*
 2015年2月6日21:08:37
 程序目的:测试findContours和drawContours函数
 局部变量监视:调试->窗口->局部变量
 使用命令行参数方法:调试->属性(Alt + F7),第一个参数默认为包含main函数的文件名,然后依次是各个参数,参数之间由空格隔开。

*/
#include"cv.h"
#include"highgui.h"

using namespace cv;
int main( int argc, char** argv )
{
 Mat src; // the first command-line parameter must be a filename of the binary
 // (black-n-white) image
 if( argc != 2 || !(src=imread(argv[1], 0)).data)
  return -1;
 printf("Rows=%d  Cols = %d\n", src.rows, src.cols);
 Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);
 src = src > 1;
 namedWindow( "Source", 1 );
 imshow( "Source", src );
 vector<vector<Point> > contours;
 vector<Vec4i> hierarchy;
 findContours( src, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
 // iterate through all the top-level contours,
 // draw each connected component with its own random color
 int idx = 0;
 for( ; idx >= 0; idx = hierarchy[idx][0] )
 {
  Scalar color( rand()&255, rand()&255, rand()&255 );
  drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
 }
  namedWindow( "Components", 1 );
  imshow( "Components", dst );
  waitKey(0);
}


/*
 时间:2015年2月6日09:01:39
 目的,求取二值图像最大联通图
 涉及到的函数FindMaxContour
 cvFindContours
 cvContourArea
 fabs
 cvBoundingRect
 cvCreateImage
 cvGetSize
 cvCopy
 cvRectangle
*/
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"

CvRect FindMaxContour(IplImage *pImg)
{

 IplImage* pContourImg = NULL;
 CvMemStorage * storage = cvCreateMemStorage(0);
 CvSeq * contour = 0;
 CvSeq *contmax = 0;
 int mode = CV_RETR_EXTERNAL;

 int area,maxArea = 10;//设面积最大值大于10Pixel
 CvRect aRect;

 cvFindContours( pImg, storage, &contour, sizeof(CvContour),mode, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));


 for(;contour;contour = contour->h_next)
 {
  area = fabs(cvContourArea( contour, CV_WHOLE_SEQ )); //获取当前轮廓面积
  //printf("area == %d\n", area);
  if(area > maxArea)
  {
   contmax = contour;
   maxArea = area;
  }
 }

 aRect = cvBoundingRect( contmax, 0 );
 return aRect;

}




0 0
原创粉丝点击