分享

OpenCV图象孔洞内轮廓填充

 叶喜勇图书馆 2014-12-26


图像内轮廓填充通常称为孔洞填充,主要用于目标提取。不带任何条件的内轮廓填充,在目标密度很大时,可能导致错误填充。一种典型情况,当多个目标粘连,并 且形成环状时,简单的内轮廓填充会将环状内部背景部分误认为目标空洞进行错误填充。这种错误对于目标分割和提取是非常致命的。


  如果将内轮廓面积作为限制条件进行填充,就可以很好解决上述问题。通常内轮廓面积应该不大于目标的最大面积。

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

#pragma comment(lib, "cv.lib")
#pragma comment(lib, "cxcore.lib") 
#pragma comment(lib, "highgui.lib")

// 内轮廓填充 
// 参数: 
// 1. pBinary: 输入二值图像,单通道,位深IPL_DEPTH_8U。
// 2. dAreaThre: 面积阈值,当内轮廓面积小于等于dAreaThre时,进行填充。 
void FillInternalContours(IplImage *pBinary, double dAreaThre) 
{ 
	double dConArea; 
	CvSeq *pContour = NULL; 
	CvSeq *pConInner = NULL; 
	CvMemStorage *pStorage = NULL; 
	// 执行条件 
	if (pBinary) 
	{ 
		// 查找所有轮廓 
		pStorage = cvCreateMemStorage(0); 
		cvFindContours(pBinary, pStorage, &pContour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); 
		// 填充所有轮廓 
		cvDrawContours(pBinary, pContour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 2, CV_FILLED, 8, cvPoint(0, 0));
		// 外轮廓循环 
		for (; pContour != NULL; pContour = pContour->h_next) 
		{ 
			// 内轮廓循环 
			for (pConInner = pContour->v_next; pConInner != NULL; pConInner = pConInner->h_next) 
			{ 
				// 内轮廓面积 
				dConArea = fabs(cvContourArea(pConInner, CV_WHOLE_SEQ)); 
				if (dConArea <= dAreaThre) 
				{ 
					cvDrawContours(pBinary, pConInner, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 0, CV_FILLED, 8, cvPoint(0, 0));
				} 
			} 
		} 
		cvReleaseMemStorage(&pStorage); 
		pStorage = NULL; 
	} 
} 
int main()  
{  
	IplImage *img = cvLoadImage(".//test.png", 0);  
	IplImage *bin = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	cvCopy(img, bin);

	FillInternalContours(bin, 200);  

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

	cvNamedWindow("result");  
	cvShowImage("result", bin);  

	cvWaitKey(-1);  

	cvReleaseImage(&img);  
	cvReleaseImage(&bin);  

	return 0;  
} 










    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多