Canny边缘检测算法可以根据像素间的差异检测出轮廓边界的像素,但是并没有将轮廓作为一个整体。
利用cvFindContours()可以实现把边缘像素组装成轮廓。
有关内存和序列的知识比较多和复杂,就不在这里详细阐述了。
下面先给出一个轮廓的例子:
给出一个窗口用于显示图像,滑动条(trackbar)用于设置阈值,然后对采二值化后的图像提取轮廓并绘制。控制参数的滑动条变化,更新图像。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
const char filename[] = "/Users/linwang/Downloads/Lena.jpg";
IplImage * g_image = cvLoadImage(filename);
IplImage * g_gray = NULL;
int g_thresh = 100;
CvMemStorage * g_storage = NULL; //存储
/*滑动条*/
void on_trackbar(int)
{
if(g_storage == NULL)
{
g_gray = cvCreateImage(cvGetSize(g_image), 8, 1);
g_storage = cvCreateMemStorage(0);
}
else
{
cvClearMemStorage(g_storage);
}
CvSeq * contours = 0; //序列
/*1、先转换成灰度图像*/
cvCvtColor(g_image,g_gray,CV_RGB2GRAY);
cvShowImage("Gray", g_gray);
/*2、二值化,转换成二值图像,0和255*/
cvThreshold(g_gray,g_gray,g_thresh,255,CV_THRESH_BINARY);
cvShowImage("double-value", g_gray);
/*3、从二值图像中检索轮廓,并返回轮廓的个数*/
cvFindContours(g_gray,g_storage,&contours);
cvZero(g_gray);
/*4、绘制轮廓*/
if(contours)
{
cvDrawContours(g_gray, contours, cvScalar(255), cvScalar(255), 100);
}
cvShowImage("Contours", g_gray);
}
int main()
{
if(g_image == NULL)
{
cout<<"Img is NULL"<<endl;
return 1;
}
cvNamedWindow("Contours",1);
cvCreateTrackbar("Threshold","Contours",&g_thresh, g_thresh ,on_trackbar);
cvShowImage("Lena", g_image);
on_trackbar(0);
cvWaitKey(0);
cvReleaseImage(&g_image);
cvReleaseImage(&g_gray);
return 0;
}