初学 OpenCV 图像加载、输出+图像轮廓提取绘制并取出每个轮廓的坐标集合

来源:互联网 发布:算法第四版 完整 pdf 编辑:程序博客网 时间:2024/06/09 13:05

OpenCV帮助文档,一般的函数参数,cv自带的数据结构等都可以在这里查到。

http://docs.opencv.org/2.4/genindex.html


include

#include<cv.h>#include<highgui.h>


load image

后面的参数,>0代表强制彩色化,0代表强制灰度化,<0代表要用alpha channel,一般用不上,通常就用1就好


IplImage* src = NULL;src = cvLoadImage ("E:/test.jpg", 1);

show image

这里就是创建一个window,再把imgshow上去,那个自动大小其实就是1。

        cvNamedWindow("show2",CV_WINDOW_AUTOSIZE);        cvShowImage("show2",img);

预处理图片

提取轮廓的图像一定是一个二值图像,所以在这之前要先把输入的图片处理一下。

下面这句话是把src转化为灰度图输出到img里,灰度图还并不是一个二值图,因此我们还需要一个函数。

 cvCvtColor (src, img, CV_BGR2GRAY);

这个tresh函数可以把一个图像二值化,下面的参数可以看一下帮助文档


参数意思就是,只要大于100的像素点,都设置为255,这里的取值范围就是0-255,否则统统为0,0就是黑色,255就是白色,我们把有颜色的尽量保留下来了。然后得到了一副二值图img

cvThreshold (img, img, 100, 255, CV_THRESH_BINARY);//大于100的都设为255,否则为0

找轮廓

之后就要对img寻找轮廓了,这里的FindContours里的参数有好几个,contours是找到的轮廓的个数,img是输入图片,contour是找到的轮廓的集合,相当于一个list,list的每个结点又是由一个轮廓的点集组成的list,最后的两个参数的意思是设置寻找的模式和方法,中文版的博客地址:

http://blog.csdn.net/qq445803843/article/details/47208687。

opencv查找轮廓---cvFindContours && cvDrawCountours 用法及例子


这里我提取了所有的轮廓,并保存了轮廓的端点,比如一个矩形,可能就只存下了4个点,要是不用SIMPLE而用NONE,就是根据图像的大小把所有点存下来,以后用着比较浪费。

        CvMemStorage* storage = cvCreateMemStorage (0);;        CvSeq* contour = 0;        int contours = 0;
        contours = cvFindContours (img, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);


绘制轮廓并取出所有轮廓点

得到的contour就是我们想要的集合了,但是他的数据结构比较复杂,我们在工程中使用OpenCV的时候还要把他的数据转化成我们自己的格式,比如Qt中有QPoint,跟OpenCV的CvPoint肯定是不兼容的,所以要把他的所有坐标取出来转化一下。

这个contour的数据结构比较奇怪,使用的时候要注意一下。

这里的contour->total是指当前轮廓的点的个数。

想要访问下一个轮廓,要用contour->h_next。

取出当前轮廓的头结点用contour->first。

从当前轮廓的头结点往下接着取后面的结点,不能用contour->first->next,这里试验后发现,头结点的next和pre都是指向了自己。。。不知道他设置这个的目的是什么。想要把一串结点取出来,他们是通过first下面的data来链接的,看下面的代码可以发现,先声明了一个指针是first的data,然后data+1就是他下一个点。


        CvScalar external_color;        CvScalar hole_color;
        for(int i=0;i<contours;i++){            external_color = CV_RGB(99, 99, 99);            hole_color = CV_RGB(0, 0, 0);            cvDrawContours (dst, contour, external_color, hole_color, 0, 2, 8);            int seqSize=contour->total;            CvSeqBlock* firstElement=contour->first;            CvPoint* curp=(CvPoint*)firstElement->data;            for(int j=0;j<seqSize;j++){                int x=curp->x;                int y=curp->y;                qDebug()<<j<<" "<<x<<" "<<y;                //curElement=curElement->next;这是不行的                ++curp;            }            contour = contour->h_next;        }


这里还有一种获取里面元素的方式,单独获取一个,挺方便的,我觉得这个复杂度是O(n)的,要连续取出一大串东西出来,每次都这样get一下,我估计就变成O(n^2)的了。

        CvPoint * firstp = (CvPoint*)cvGetSeqElem(contour, 3);

画轮廓的时候有些参数需要注意一下


后面那3个参数,后俩一个是画线的厚度一个是线的类型,这个maxlevel要注意一下,0是只画当前的轮廓,1是画一层嵌套的,2是画所有的,为了方便调试,我多画几次,每次只画一个轮廓。


最后。。。

        cvWaitKey (0);        cvReleaseMemStorage (&storage);        cvReleaseImage (&src);        cvReleaseImage (&img);        cvReleaseImage (&dst);









1 0