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