您的位置:首页 > 其它

cvFindContours/findContours提取轮廓

2014-07-25 17:08 183 查看
opencv在提取轮廓时,C/C++有两种方式,有些许不同,结合查找的资料和补充,做个小笔记;

功能,提取满足一定面积阈值和宽高比例的轮廓;

主函数

static int getContoursByC(char* Imgname, double minarea = 100, double whRatio = 1);
static int getContoursByCplus(char* Imgname, double minarea=0, double whRatio=1);
int main()
{
char* filename = new char[50];
strcpy(filename, "../image/rl_4.jpg");
getContoursByCplus(filename);
delete[] filename;
return 0;
}


API实现

cvFindContours形式

/*采用cvFindContours提取轮廓,并过滤掉小面积轮廓,最后将轮廓保存*/
static int getContoursByC(char* Imgname, double minarea, double whRatio)
{
IplImage* src = cvLoadImage(Imgname, CV_LOAD_IMAGE_GRAYSCALE);
if (!src)
{
printf("read data error!\n");
return -1;
}
IplImage* dst = cvCreateImage(cvGetSize(src), 8, 3);

//the parm. for cvFindContours
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;
double maxarea = 0;

//for display
cvNamedWindow("Source", CV_WINDOW_NORMAL);
cvShowImage("Source", src);

//二值化
cvThreshold(src, src, 120, 255, CV_THRESH_BINARY);

//提取轮廓
cvFindContours(src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
cvZero(dst);//清空数组

/*CvSeq* _contour为了保存轮廓的首指针位置,因为随后contour将用来迭代*/
CvSeq* _contour = contour;

int maxAreaIdx = -1, iteratorIdx = 0;//n为面积最大轮廓索引,m为迭代索引
for (int iteratorIdx = 0; contour != 0; contour = contour->h_next, iteratorIdx++/*更新迭代索引*/)
{

double tmparea = fabs(cvContourArea(contour));
if (tmparea > maxarea)
{
maxarea = tmparea;
maxAreaIdx = iteratorIdx;
continue;
}
if (tmparea < minarea)
{
//删除面积小于设定值的轮廓
cvSeqRemove(contour, 0);
continue;
}
CvRect aRect = cvBoundingRect(contour, 0);
if ((aRect.width / aRect.height)<whRatio)
{
//删除宽高比例小于设定值的轮廓
cvSeqRemove(contour, 0);
continue;
}
//CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );//创建一个色彩值
//CvScalar color = CV_RGB(0, 255, 255);

//max_level 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。
//如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。
//如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。
//cvDrawContours(dst, contour, color, color, -1, 1, 8);//绘制外部和内部的轮廓
}
contour = _contour; /*int k=0;*/
//统计剩余轮廓,并画出最大面积的轮廓
int count = 0;
for (; contour != 0; contour = contour->h_next)
{
count++;
double tmparea = fabs(cvContourArea(contour));
if (tmparea == maxarea /*k==n*/)
{
CvScalar color = CV_RGB(255, 0, 0);
cvDrawContours(dst, contour, color, color, -1, 1, 8);
}
/*k++;*/
}
printf("The total number of contours is:%d", count);
cvNamedWindow("Components", CV_WINDOW_NORMAL);
cvShowImage("Components", dst);
cvSaveImage("dst.jpg", dst);
//roateProcess(dst);
cvWaitKey(0);
//销毁窗口和图像存储
cvDestroyWindow("Source");
cvReleaseImage(&src);
cvDestroyWindow("Components");
cvReleaseImage(&dst);
return 0;
}


findContours形式

static int getContoursByCplus(char* Imgname, double minarea, double whRatio)
{
cv::Mat src, dst, canny_output;
/// Load source image and convert it to gray
src = imread(Imgname, 0);

if (!src.data)
{
std::cout << "read data error!" << std::endl;
return -1;
}
blur(src, src, Size(3, 3));

//the pram. for findContours,
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

/// Detect edges using canny
Canny(src, canny_output, 80, 255, 3);
/// Find contours
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE

double maxarea = 0;
int maxAreaIdx = 0;

for (int i = 0; i<contours.size(); i++)
{

double tmparea = fabs(contourArea(contours[i]));
if (tmparea>maxarea)
{
maxarea = tmparea;
maxAreaIdx = i;
continue;
}

if (tmparea < minarea)
{
//删除面积小于设定值的轮廓
contours.erase(contours.begin() + i);
std::wcout << "delete a small area" << std::endl;
continue;
}
//计算轮廓的直径宽高
Rect aRect =boundingRect(contours[i]);
if ((aRect.width / aRect.height)<whRatio)
{
//删除宽高比例小于设定值的轮廓
contours.erase(contours.begin() + i);
std::wcout << "delete a unnomalRatio area" << std::endl;
continue;
}
}
/// Draw contours,彩色轮廓
dst= Mat::zeros(canny_output.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
//随机颜色
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, i, color, 2, 8, hierarchy, 0, Point());
}
// Create Window
char* source_window = "countors";
namedWindow(source_window, CV_WINDOW_NORMAL);
imshow(source_window, dst);
cv:; waitKey(0);

return 0;
}



之后



over!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: