• OPENCV形态学操作1


    形态学操作是指基于形状的一系列图像处理操作,包括膨胀,腐蚀,二值化,开运算,闭运算,顶帽算法,黑帽算法,形态学梯度等,最基本的形态学操作就是膨胀和腐蚀.

    一.膨胀

             首先需要明确一个概念,膨胀和腐蚀都是针对于图像中较亮的区域而言的,膨胀就是亮的区域变多了,而腐蚀就是暗的区域变多了.

             膨胀的功能主要有消除噪声,分割出独立的图像元素,在图像操作的时候,有时候需要对图像中的某些形状进行检测,而这些形状相互连接在一起,不好分开检测,膨胀就能切开这些形状(很小的连接位置),或者图像中有很小块的黑斑,或许是相机上的影响,膨胀,也能消除这些小的黑斑

             膨胀的基本思路就是图像与一个核函数进行卷积,并取出结果中的极大值作为结果,使得图像中的高亮区域增长.这个核的形状,锚点都可以进行设置,OPENCV提供了API供我们获得核.

             API:Mat getStructuringElement(int 内核形状,Size 内核尺寸,Point 锚点位置)

             注:内核形状可以取方形MORPH_RECT,十字形MORPH_CROSS,椭圆形MORPH_ELLIPSE

                      锚点位置默认值Point(-1,-1),取形状的中心

             通过该API就可以获得相应的计算核,接下来计算膨胀的函数为

             API:void dilate(源图像,目标图像,膨胀核,锚点,int 迭代次数,int边界模式,int 边界为常数时边界值)

             注:该API支持in_place(源图像可以做目的图像参数,算法会修改源图像内数据),迭代次数默认为1

    例子如下

    Mat srcImage;
    //膨胀
    const int g_dilateIterMax = 100;//迭代次数
    int g_nDilateIterValue;
    const int g_dilateCoreMax = 100;//核大小
    int g_nDilateCoreValue;
    Mat dilateImage;
    void OnDilateIterTrackbar(int pos,void* userData);
    void onDilateCoreSizeTrackBar(int pos,void* userData);
    
    int main(int argc,char* argv)
    {
    	srcImage = imread("F:\opencv\OpenCVImage\erode_dilate.jpg");
    	namedWindow("src image");
    	namedWindow("dilate image");
    
    	g_nDilateIterValue = 1;
    	g_nDilateCoreValue = 5;
    	createTrackbar("inter count", "dilate image", &g_nDilateIterValue, g_dilateIterMax,OnDilateIterTrackbar);
    	createTrackbar("core size", "dilate image", &g_nDilateCoreValue, g_dilateCoreMax,onDilateCoreSizeTrackBar);
    	OnDilateIterTrackbar(g_nDilateIterValue,0);
    
    	moveWindow("src image", 0, 0);
    	moveWindow("dilate image", srcImage.cols, 0);
    
    	imshow("src image", srcImage);
    
    	waitKey(0);
    	return 0;	
    }
    
    //调整迭代次数
    void OnDilateIterTrackbar(int pos,void* userData)
    {
       if(pos == 0||g_nDilateCoreValue == 0)
       {
           imshow("dilate image", srcImage);
       }
       else
       {
           if(g_nDilateCoreValue%2 == 0)
           {
               g_nDilateCoreValue++;
           }
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nDilateCoreValue,g_nDilateCoreValue));
           dilate(srcImage, dilateImage, core,Point(-1,-1),g_nDilateIterValue);
           imshow("dilate image", dilateImage);
       }
    }
    
    //调整核大小
    void onDilateCoreSizeTrackBar(int pos,void* userData)
    {
       if(pos == 0 || g_nDilateIterValue == 0)
       {
           imshow("dilate image", srcImage);
       }
       else
       {
           if(g_nDilateCoreValue%2 == 0)
           {
               g_nDilateCoreValue++;
           }
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nDilateCoreValue,g_nDilateCoreValue));
           dilate(srcImage, dilateImage, core,Point(-1,-1),g_nDilateIterValue);
           imshow("dilate image", dilateImage);
       }
    }
    

      

    二.腐蚀

             腐蚀与膨胀正好相反,是求局部最小值的操作,亮的地方会减少,黑的地方会增多,在图像中连接接近的区域,消除高亮造成的噪声

             API: void erode(源,目的,核,锚点,迭代次数,边缘类型,边缘为常数时边界值);

             注:腐蚀和膨胀API的形式一致

    使用代码

    //腐蚀
    Mat srcImage;
    const int g_erodeIterMax = 100;
    int g_nErodeIterValue;
    const int g_erodeCoreMax = 100;
    int g_nErodeCoreValue;
    Mat erodeImage;
    void OnErodeIterTrackbar(int pos,void* userData);
    void onErodeCoreSizeTrackBar(int pos,void* userData);
    
    int main(int argc,char* argv)
    
    {
    	srcImage = imread("F:\opencv\OpenCVImage\erode_dilate.jpg");
    	namedWindow("src image");
        namedWindow("erode image");
    
       g_nErodeIterValue = 1;
       g_nErodeCoreValue = 5;
       createTrackbar("inter count", "erode image", &g_nErodeIterValue, g_erodeIterMax,OnErodeIterTrackbar);
       createTrackbar("core size", "erode image", &g_nErodeCoreValue, g_erodeCoreMax,onErodeCoreSizeTrackBar);
       OnErodeIterTrackbar(g_nErodeIterValue, 0);
    
    	moveWindow("src image", 0, 0);
        moveWindow("erode image", srcImage.cols, 0);
    
    	imshow("src image", srcImage);
    	waitKey(0);
    	return 0;	
    
    }
    
    //调整迭代次数
    void OnErodeIterTrackbar(int pos,void* userData)
    {
       if(pos == 0 || g_nErodeCoreValue == 0)
       {
           imshow("erode image", srcImage);
       }
       else
       {
           if(g_nErodeCoreValue%2 == 0)
           {
               g_nErodeCoreValue++;
           }
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nErodeCoreValue,g_nErodeCoreValue),Point(-1,-1));
           erode(srcImage, erodeImage, core,Point(-1,-1),g_nErodeIterValue);
           imshow("erode image", erodeImage);
       }
    }
    //调整核大小
    void onErodeCoreSizeTrackBar(int pos,void* userData)
    {
       if(pos == 0 || g_nErodeIterValue == 0)
       {
           imshow("erode image", srcImage);
       }
       else
       {
           if(g_nErodeCoreValue%2 == 0)
           {
               g_nErodeCoreValue++;
           }
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nErodeCoreValue,g_nErodeCoreValue),Point(-1,-1));
           erode(srcImage, erodeImage, core,Point(-1,-1),g_nErodeIterValue);
           imshow("erode image", erodeImage);
       }
    }
    

      

    三.形态学滤波算法

             形态学的高级操作,往往都建立在基础的膨胀和腐蚀的操作之上

             1.开运算:开运算是一个先腐蚀,后膨胀的过程,用于在图像中消除小的物体,在纤细点处分离物体,在平滑化较大的物体的边界的同时不明显改变物体的体积.

             2.闭运算:先膨胀后腐蚀的过程,能够用于消除物体中的小型黑洞

             3.形态学梯度:膨胀图和腐蚀图之差,对二值图像进行这一操作,可以将团块的边缘突出来,可以使用形态学梯度来保留物体的边缘轮廓.

             4.顶帽:源图像和开运算的结果的差值,往往用来分离比邻近点亮一点的斑块,在一幅图具体大幅的背景,而微小物体有比较有规律的情况下,可以使用top_hat运算进行背景的提取

             5.黑帽:闭运算的结果与源图像之差,突出了比源图像轮廓周围更暗的区域,往往用于分离比邻近点暗一些的斑块.

             核心API:void morpholgyEx(源,目标,int 形态学操作标志,mat 形态学操作内核,Point 锚点,int 迭代次数,int 边界模式,int 边界为常数时的边界值).

             注:形态学操作标志的取值如下:MORPH_OPEN开运算  MORPH_CLOSE 闭运算 MORPH_GRENIENT 形态学梯度 MORPH_TOPHAT顶帽 MORPH_BLACKHAT黑帽 MORPH_ERODE腐蚀 MORPH_DILATE 膨胀

                      形态学操作内核就是前面膨胀腐蚀使用的内核.

    使用范例如下:

    1.开运算 闭运算 形态学梯度三者联合

    //源¡ä图ª?像?
    Mat srcImage;
    
    //开a运?算?
    const int g_openIterMax = 100;
    int g_nopenIterValue;
    const int g_openCoreMax = 100;
    int g_nopenCoreValue;
    Mat openImage;
    void OnopenIterTrackbar(int pos,void* userData);
    void onopenCoreSizeTrackBar(int pos,void* userData);
    
    //闭À?运?算?
    const int g_closeIterMax = 100;
    int g_ncloseIterValue;
    const int g_closeCoreMax = 100;
    int g_ncloseCoreValue;
    Mat closeImage;
    void OncloseIterTrackbar(int pos,void* userData);
    void oncloseCoreSizeTrackBar(int pos,void* userData);
    
    //形?态¬?学¡ì梯¬Y度¨¨
    const int g_gredientIterMax = 100;
    int g_ngredientIterValue;
    const int g_gredientCoreMax = 100;
    int g_ngredientCoreValue;
    Mat gredientImage;
    void OngredientIterTrackbar(int pos,void* userData);
    void ongredientCoreSizeTrackBar(int pos,void* userData);
    
    
    int main(int argc,char* argv[])
    {
       srcImage = imread("F:\opencv\OpenCVImage\morpholgy.jpg");
       
       g_nopenIterValue = 1;
       g_nopenCoreValue = 5;
       namedWindow("open image");
       createTrackbar("iter count", "open image", &g_nopenIterValue, g_openIterMax,OnopenIterTrackbar,0);
       createTrackbar("core size", "open image", &g_nopenCoreValue, g_openCoreMax,onopenCoreSizeTrackBar,0);
       onopenCoreSizeTrackBar(g_nopenCoreValue, 0);
       
       g_ncloseCoreValue = 5;
       g_ncloseIterValue = 1;
       namedWindow("close image");
       createTrackbar("iter count", "close image", &g_ncloseIterValue, g_closeIterMax,OncloseIterTrackbar,0);
       createTrackbar("core size", "close image", &g_ncloseCoreValue, g_closeCoreMax,oncloseCoreSizeTrackBar,0);
       oncloseCoreSizeTrackBar(g_ncloseCoreValue, 0);
       
       g_ngredientCoreValue = 5;
       g_ngredientIterValue = 1;
       namedWindow("gredient image");
       createTrackbar("iter count", "gredient image", &g_ngredientIterValue, g_gredientIterMax,OngredientIterTrackbar,0);
       createTrackbar("core size", "gredient image", &g_ngredientCoreValue, g_gredientCoreMax,OngredientIterTrackbar,0);
       OngredientIterTrackbar(g_ngredientIterValue, 0);
       
       imshow("src image", srcImage);
      
       moveWindow("src image", 0, 0);
       moveWindow("open image", srcImage.cols, 0);
       moveWindow("close image", srcImage.cols*2, 0);
       moveWindow("gredient image", srcImage.cols*3, 0);
       
       waitKey(0);
       return 0;
    }
    
    void OnopenIterTrackbar(int pos,void* userData)
    {
       if(g_nopenCoreValue == 0||g_nopenIterValue == 0)
       {
           imshow("open image", srcImage);
       }
       else
       {
           if(g_nopenCoreValue%2 == 0)
               g_nopenCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nopenCoreValue,g_nopenCoreValue));
           morphologyEx(srcImage, openImage, MORPH_OPEN, core,Point(-1,-1),g_nopenIterValue);
           imshow("open image", openImage);
       }
    }
    void onopenCoreSizeTrackBar(int pos,void* userData)
    {
       if(g_nopenCoreValue == 0||g_nopenIterValue == 0)
       {
           imshow("open image", srcImage);
       }
       else
       {
           if(g_nopenCoreValue%2 == 0)
               g_nopenCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nopenCoreValue,g_nopenCoreValue));
           morphologyEx(srcImage, openImage, MORPH_OPEN, core,Point(-1,-1),g_nopenIterValue);
           imshow("open image", openImage);
       }
    }
    void OncloseIterTrackbar(int pos,void* userData)
    {
       if(g_ncloseCoreValue == 0||g_ncloseIterValue == 0)
       {
           imshow("close image", srcImage);
       }
       else
       {
           if(g_ncloseCoreValue%2 == 0)
               g_ncloseCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_ncloseCoreValue,g_ncloseCoreValue));
           morphologyEx(srcImage, closeImage, MORPH_CLOSE, core,Point(-1,-1),g_ncloseIterValue);
           imshow("close image", closeImage);
       }
    }
    void oncloseCoreSizeTrackBar(int pos,void* userData)
    {
       if(g_ncloseCoreValue == 0||g_ncloseIterValue == 0)
       {
           imshow("close image", srcImage);
       }
       else
       {
           if(g_ncloseCoreValue%2 == 0)
               g_ncloseCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_ncloseCoreValue,g_ncloseCoreValue));
           morphologyEx(srcImage, closeImage, MORPH_CLOSE, core,Point(-1,-1),g_ncloseIterValue);
           imshow("close image", closeImage);
       }
    }
    void OngredientIterTrackbar(int pos,void* userData)
    {
       if(g_ngredientCoreValue == 0||g_ngredientIterValue == 0)
       {
           imshow("gredient image", srcImage);
       }
       else
       {
           if(g_ngredientCoreValue%2 == 0)
               g_ngredientCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_ngredientCoreValue,g_ngredientCoreValue));
           morphologyEx(srcImage, gredientImage, MORPH_GRADIENT, core,Point(-1,-1),g_ngredientIterValue);
           imshow("gredient image", gredientImage);
       }
    }
    void ongredientCoreSizeTrackBar(int pos,void* userData)
    {
       if(g_ngredientCoreValue == 0||g_ngredientIterValue == 0)
       {
           imshow("gredient image", srcImage);
       }
       else
       {
           if(g_ngredientCoreValue%2 == 0)
               g_ngredientCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_ngredientCoreValue,g_ngredientCoreValue));
           morphologyEx(srcImage, gredientImage, MORPH_GRADIENT, core,Point(-1,-1),g_ngredientIterValue);
           imshow("gredient image", gredientImage);
       }
    }
    

      

    2. 顶帽 黑帽结合

    Mat srcImage;
    
    //顶£¤帽¡À tophat
    const int g_tophatIterMax = 100;
    int g_ntophatIterValue;
    const int g_tophatCoreMax = 100;
    int g_ntophatCoreValue;
    Mat tophatImage;
    void OntophatIterTrackbar(int pos,void* userData);
    void ontophatCoreSizeTrackBar(int pos,void* userData);
    
    //黑¨²帽¡À
    const int g_blackhatIterMax = 100;
    int g_nblackhatIterValue;
    const int g_blackhatCoreMax = 100;
    int g_nblackhatCoreValue;
    Mat blackhatImage;
    void OnblackhatIterTrackbar(int pos,void* userData);
    void onblackhatCoreSizeTrackBar(int pos,void* userData);
    
    
    int main(int argc,char* argv[])
    {
       srcImage = imread("F:\opencv\OpenCVImage\morpholgy.jpg");
       
       g_ntophatIterValue = 1;
       g_ntophatCoreValue = 5;
       namedWindow("tophat image");
       createTrackbar("iter count", "tophat image", &g_ntophatIterValue, g_tophatIterMax,OntophatIterTrackbar,0);
       createTrackbar("core size", "tophat image", &g_ntophatCoreValue, g_tophatCoreMax,ontophatCoreSizeTrackBar,0);
       ontophatCoreSizeTrackBar(g_ntophatCoreValue, 0);
       
       g_nblackhatCoreValue = 5;
       g_nblackhatIterValue = 1;
       namedWindow("blackhat image");
       createTrackbar("iter count", "blackhat image", &g_nblackhatIterValue, g_blackhatIterMax,OnblackhatIterTrackbar,0);
       createTrackbar("core size", "blackhat image", &g_nblackhatCoreValue, g_blackhatCoreMax,onblackhatCoreSizeTrackBar,0);
       onblackhatCoreSizeTrackBar(g_nblackhatCoreValue, 0);
       
       imshow("src image", srcImage);
       
       moveWindow("src image", 0, 0);
       moveWindow("tophat image", srcImage.cols, 0);
       moveWindow("blackhat image", srcImage.cols*2, 0);
       
       waitKey(0);
       return 0;
    }
    
    void OntophatIterTrackbar(int pos,void* userData)
    {
       if(g_ntophatCoreValue == 0||g_ntophatIterValue == 0)
       {
           imshow("tophat image", srcImage);
       }
       else
       {
           if(g_ntophatCoreValue%2 == 0)
               g_ntophatCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_ntophatCoreValue,g_ntophatCoreValue));
           morphologyEx(srcImage, tophatImage, MORPH_TOPHAT, core,Point(-1,-1),g_ntophatIterValue);
           imshow("tophat image", tophatImage);
       }
    }
    void ontophatCoreSizeTrackBar(int pos,void* userData)
    {
       if(g_ntophatCoreValue == 0||g_ntophatIterValue == 0)
       {
           imshow("tophat image", srcImage);
       }
       else
       {
           if(g_ntophatCoreValue%2 == 0)
               g_ntophatCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_ntophatCoreValue,g_ntophatCoreValue));
           morphologyEx(srcImage, tophatImage, MORPH_TOPHAT, core,Point(-1,-1),g_ntophatIterValue);
           imshow("tophat image", tophatImage);
       }
    }
    
    
    void OnblackhatIterTrackbar(int pos,void* userData)
    {
       if(g_nblackhatCoreValue == 0||g_nblackhatIterValue == 0)
       {
           imshow("blackhat image", srcImage);
       }
       else
       {
           if(g_nblackhatCoreValue%2 == 0)
               g_nblackhatCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nblackhatCoreValue,g_nblackhatCoreValue));
           morphologyEx(srcImage, blackhatImage, MORPH_BLACKHAT, core,Point(-1,-1),g_nblackhatIterValue);
           imshow("blackhat image", blackhatImage);
       }
    }
    void onblackhatCoreSizeTrackBar(int pos,void* userData)
    {
       if(g_nblackhatCoreValue == 0||g_nblackhatIterValue == 0)
       {
           imshow("blackhat image", srcImage);
       }
       else
       {
           if(g_nblackhatCoreValue%2 == 0)
               g_nblackhatCoreValue++;
           Mat core = getStructuringElement(MORPH_RECT, Size(g_nblackhatCoreValue,g_nblackhatCoreValue));
           morphologyEx(srcImage, blackhatImage, MORPH_BLACKHAT, core,Point(-1,-1),g_nblackhatIterValue);
           imshow("blackhat image", blackhatImage);
       }
    }
    

      

  • 相关阅读:
    带掩码的自编码器MAE详解和Pytorch代码实现
    联邦学习(Federated Learning)详解以及示例代码
    SIMILAR:现实场景中基于子模块信息度量的主动学习
    BERT 模型的知识蒸馏: DistilBERT 方法的理论和机制研究
    为什么 Pi 会出现在正态分布的方程中?
    快到周五了
    土豆
    忙碌的周末
    周五了
    写给妹妹的祝福语
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/5249052.html
Copyright © 2020-2023  润新知