如果将内轮廓面积作为限制条件进行填充,就可以很好解决上述问题。通常内轮廓面积应该不大于目标的最大面积。
#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; }