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

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

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


include

#include
#include


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函数可以把一个图像二值化,下面的参数可以看一下帮助文档

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

参数意思就是,只要大于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 用法及例子

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

这里我提取了所有的轮廓,并保存了轮廓的端点,比如一个矩形,可能就只存下了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;itotal;
            CvSeqBlock* firstElement=contour->first;
            CvPoint* curp=(CvPoint*)firstElement->data;
            for(int j=0;jx;
                int y=curp->y;
                qDebug()<next;这是不行的
                ++curp;
            }
            contour = contour->h_next;
        }


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

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

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

初学 OpenCV 图像加载、输出+图像轮廓提取绘制并取出每个轮廓的坐标集合_第3张图片
后面那3个参数,后俩一个是画线的厚度一个是线的类型,这个maxlevel要注意一下,0是只画当前的轮廓,1是画一层嵌套的,2是画所有的,为了方便调试,我多画几次,每次只画一个轮廓。


最后。。。

        cvWaitKey (0);

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









你可能感兴趣的:(工作)