opencv 刪除二值化圖像中面積較小的連通域


對於上圖的二值化圖像,要去除左下角和右上角的噪點,方法:使用opencv去掉黑色面積較小的連通域。

代碼

 CvSeq* contour = NULL;   
   double minarea = 100.0;   
   double tmparea = 0.0;   
CFileDialog dlg(true);   
if (dlg.DoModal()==IDOK)   
{   
    CvMemStorage* storage = cvCreateMemStorage(0);   
       
    IplImage* img_src= cvLoadImage(dlg.GetPathName(),CV_LOAD_IMAGE_ANYCOLOR);   
    IplImage* img_Clone=cvCloneImage(img_src);   
    //訪問二值圖像每個點的值   
    uchar *pp;   
    //顯示原始圖像   
    cvNamedWindow("img_src",CV_WINDOW_AUTOSIZE);   
    cvShowImage("img_src", img_src);   
       
    IplImage* img_dst = cvCreateImage(cvGetSize(img_src),IPL_DEPTH_8U,1);   
       
    //------------搜索二值圖中的輪廓,並從輪廓樹中刪除面積小於某個閾值minarea的輪廓-------------//   
    CvScalar color = cvScalar(255,0,0);//CV_RGB(128,0,0);   
    CvContourScanner scanner = NULL;   
scanner = cvStartFindContours(img_src,storage,sizeof(CvContour),CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE,cvPoint(0,0));   
    //開始遍歷輪廓樹   
    CvRect rect;   
    while (contour=cvFindNextContour(scanner))   
    {   
        tmparea = fabs(cvContourArea(contour));   
            rect = cvBoundingRect(contour,0);      
        if (tmparea < minarea/*||tmparea>4900*/)   
        {   
           
        //當連通域的中心點為黑色時,而且面積較小則用白色進行填充   
            pp=(uchar*)(img_Clone->imageData + img_Clone->widthStep*(rect.y+rect.height/2)+rect.x+rect.width/2);   
            if (pp[0]==0)   
            {   
                for(int y = rect.y;y<rect.y+rect.height;y++)   
                {   
                    for(int x =rect.x;x<rect.x+rect.width;x++)   
                    {   
                        pp=(uchar*)(img_Clone->imageData + img_Clone->widthStep*y+x);   
                           
                        if (pp[0]==0)   
                        {   
                            pp[0]=255;   
                        }   
                    }   
                }   
            }   
           
        }   
    }   
cvSaveImage("c://temp//aav.bmp",img_Clone);  

分析:對於上圖來說連通域共有: 

這么七個,我們的目標是去除2號和3號連通域,

程序中語句 tmparea = fabs(cvContourArea(contour));可以得到當前連通域的面積,當此面積小於閾值時對其填充為白色。

rect = cvBoundingRect(contour,0); 得到的是框住連通域的最小矩形,對矩形中的黑色部分將其填充為白色,但是這樣的話,連通域6和4兩個連通域被填充成了白色的矩形,這顯然不符合我們的要求,這樣就要判斷此連通域是黑色聯通域還是白色連通域,采用的方法是測試矩形的中心點,如果其為黑色,則認為此連通域是黑色連通域,否則為白色聯通域,對於黑色聯通域我們對其進行白色填充處理,對於白色聯通域則保持不變。

原文地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM