OpenCV圖象孔洞內輪廓填充
阿新 • • 發佈:2018-12-19
影象內輪廓填充通常稱為孔洞填充,主要用於目標提取。不帶任何條件的內輪廓填充,在目標密度很大時,可能導致錯誤填充。一種典型情況,當多個目標粘連,並 且形成環狀時,簡單的內輪廓填充會將環狀內部背景部分誤認為目標空洞進行錯誤填充。這種錯誤對於目標分割和提取是非常致命的。
如果將內輪廓面積作為限制條件進行填充,就可以很好解決上述問題。通常內輪廓面積應該不大於目標的最大面積。
#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; }