精华内容
下载资源
问答
  • OpenCV形态学操作

    2019-02-22 20:00:01
    OpenCV形态学操作

    分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

                   

    OpenCV形态学操作

     

    一、图像腐蚀 膨胀 细化的基本原理

    1.图像细化的基本原理
    图像形态学处理的概念
    数字图像处理中的形态学处理是指将数字形态学作为工具从图像中提取对于表达和描绘区域形状有用处的图像分量,比如边界、骨架以及凸壳,还包括用于预处理或后处理的形态学过滤、细化和修剪等。图像形态学处理中我们感兴趣的主要是二值图像。
    在二值图像中,所有黑色像素的集合是图像完整的形态学描述,二值图像的各个分量是Z2的元素。假定二值图像A和形态学处理的结构元素B是定义在笛卡儿网格上的集合,网格中值为1的点是集合的元素,当结构元素的原点移到点(x,y)时,记为Sxy,为简单起见,结构元素为3x3,且全都为1,在这种限制下,决定输出结果的是逻辑运算。

    二值图像的逻辑运算
    逻辑运算尽管本质上很简单,但对于实现以形态学为基础额图像处理算法是一种有力的补充手段。在图像处理中用到的主要逻辑运算是:与、或和非(求补),它们可以互相组合形成其他逻辑运算。

    膨胀和腐蚀
    膨胀和腐蚀这两种操作是形态学处理的基础,许多形态学算法都是以这两种运算为基础的。
    膨胀
    是以得到B的相对与它自身原点的映像并且由z对映像进行移位为基础的。AB膨胀是所有位移z的集合,这样, 和A至少有一个元素是重叠的。我们可以把上式改写为:
    结构元素B可以看作一个卷积模板,区别在于膨胀是以集合运算为基础的,卷积是以算术运算为基础的,但两者的处理过程是相似的。
    用结构元素B,扫描图像A的每一个像素
    用结构元素与其覆盖的二值图像做操作
    如果都为0,结果图像的该像素为0。否则为1

    腐蚀
    Z中的集合ABBA进行腐蚀的整个过程如下:
    用结构元素B,扫描图像A的每一个像素
    用结构元素与其覆盖的二值图像做操作
    如果都为1,结果图像的该像素为1。否则为0
    腐蚀处理的结果是使原来的二值图像减小一圈。

    击中(匹配)或击不中变换
    假设集合A是由3个子集XYZ组成的集合,击中(匹配)的目的是要在A中找到X的位置,我们设X被包围在一个小窗口W中,与W有关的X的局部背景定义为集合的差(WX),则XA内能得到精确拟合位置集合是由XA的腐蚀后由(WX)对A的补集Ac腐蚀的交集,这个交集就是我们要找的位置,我们用集合B来表示由XX的背景构成的集合,我们可以令B=(B1B2),这里B1XB2=(WX),则在A中对B进行匹配可以表示为:
    A⊙B
    我们称为形态学上的击中或击不中变换。

     

    开闭操作
    开操作是先腐蚀、后膨胀处理。

    闭操作是先膨胀、后腐蚀处理。

     

    (6) 细化
    图像细化一般作为一种图像预处理技术出现,目的是提取源图像的骨架,即是将原图像中线条宽度大于1个像素的线条细化成只有一个像素宽,形成骨架,形成骨架后能比较容易的分析图像,如提取图像的特征。
    细化基本思想是层层剥夺,即从线条边缘开始一层一层向里剥夺,直到线条剩下一个像素的为止。图像细化大大地压缩了原始图像地数据量,并保持其形状的基本拓扑结构不变,从而为文字识别中的特征抽取等应用奠定了基础。细化算法应满足以下条件:
    将条形区域变成一条薄线;
    薄线应位与原条形区域的中心;
    薄线应保持原图像的拓扑特性。
    细化分成串行细化和并行细化,串行细化即是一边检测满足细化条件的点,一边删除细化点;并行细化即是检测细化点的时候不进行点的删除只进行标记,而在检测完整幅图像后一次性去除要细化的点。
    常用的图像细化算法有hilditch算法,pavlidis算法和rosenfeld算法等。
    注:进行细化算法前要先对图像进行二值化,即图像中只包含两种颜色。

    具体详细的图像形态学资料参考:http://wenku.baidu.com/view/1923d18fcc22bcd126ff0ccc.html

     

    二、OpenCv形态学操作相关函数

    1MorphologyEx         高级形态学变换

    void cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp,
    IplConvKernel* element, int operation, int iterations=1 );
    src
    输入图像.
    dst
    输出图像.
    temp
    临时图像,某些情况下需要
    element
    结构元素
    operation
    形态操作的类型:
    CV_MOP_OPEN -
    开运算
    CV_MOP_CLOSE -
    闭运算
    CV_MOP_GRADIENT -
    形态梯度
    CV_MOP_TOPHAT - "
    顶帽"
    CV_MOP_BLACKHAT - "
    黑帽"
    iterations
    膨胀和腐蚀次数.
    函数 cvMorphologyEx 在膨胀和腐蚀基本操作的基础上,完成一些高级的形态变换:

    开运算
    dst=open(src,element)=dilate(erode(src,element),element)
    闭运算
    dst=close(src,element)=erode(dilate(src,element),element)
    形态梯度
    dst=morph_grad(src,element)=dilate(src,element)-erode(src,element)
    "
    顶帽"
    dst=tophat(src,element)=src-open(src,element)
    "
    黑帽"
    dst=blackhat(src,element)=close(src,element)-src
    临时图像 temp 在形态梯度以及对顶帽黑帽操作时的 in-place 模式下需要。

    2Dilate    使用任意结构元素膨胀图像

    void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
    src
    输入图像.
    dst
    输出图像.
    element
    用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
    iterations
    膨胀的次数
    函数 cvDilate 对输入图像使用指定的结构元进行膨胀,该结构决定每个具有最小值象素点的邻域形状:
    dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
    函数支持(in-place)模式。膨胀可以重复进行 (iterations) . 对彩色图像,每个彩色通道单独处理。

    3Erode    使用任意结构元素腐蚀图像

    void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
    src
    输入图像.
    dst
    输出图像.
    element
    用于腐蚀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
    iterations
    腐蚀的次数
    函数 cvErode 对输入图像使用指定的结构元素进行腐蚀,该结构元素决定每个具有最小值象素点的邻域形状:
    dst=erode(src,element): dst(x,y)=min((x',y') in element))src(x+x',y+y')
    函数可能是本地操作,不需另外开辟存储空间的意思。腐蚀可以重复进行 (iterations) . 对彩色图像,每个彩色通道单独处理。

    注:CreateStructuringElementEx  创建结构元素;ReleaseStructuringElement 删除结构元素。

     

    三、OpenCv形态学实例代码:

    1、腐蚀、膨胀、开运算、闭运算

    内容参考:http://blog.csdn.net/gnuhpc/archive/2009/06/21/4286177.aspx

    /******************************* 

    数学形态运算,最常见的基本运算有七种, 

    分别为:腐蚀、膨胀、开运算、闭运算、击中、细化和粗化, 

    它们是全部形态学的基础。 

    ********************************/ 

    #include "cv.h"  

    #include "highgui.h"  

    #include <stdlib.h>  

    #include <stdio.h>  

    IplImage *src=0;  

    IplImage *dst=0;  

    IplConvKernel *element=0;//声明一个结构元素  

    int element_shape=CV_SHAPE_RECT;//长方形形状的元素  

    int max_iters=10;  

    int open_close_pos=0;  

    int erode_dilate_pos=0;  

    void OpenClose(int pos)  

    {  

        int n=open_close_pos-max_iters;  

        int an=n>0?n:-n;  

        element = cvCreateStructuringElementEx(an*2+1,   an*2+1,an,an,element_shape,0);//创建结构元素  

         

        if (n<0)  

        {  

            cvErode(src,dst,element,1);//腐蚀图像  

            cvDilate(dst,dst,element,1);//膨胀图像  

        }  

        else 

        {         

            cvDilate(dst,dst,element,1);//膨胀图像  

            cvErode(src,dst,element,1);//腐蚀图像  

        }  

        cvReleaseStructuringElement(&element);  

        cvShowImage("Open/Close",dst);  

    }  

    void ErodeDilate(int pos)  

    {  

        int n=erode_dilate_pos-max_iters;  

        int an=n>0?n:-n;  

        element = cvCreateStructuringElementEx(an*2+1,an*2+1,an,an,element_shape,0);  

        if (n<0)  

        {  

            cvErode(src,dst,element,1);  

        }  

        else 

        {  

            cvDilate(src,dst,element,1);  

        }  

        cvReleaseStructuringElement(&element);  

        cvShowImage("Erode/Dilate",dst);  

    }  

    int main(int argc,char **argv)  

    {  

        char *filename =argc ==2?argv[1]:(char *)"lena.jpg";      

        if( (src = cvLoadImage(filename,1)) == 0 )  

            return -1;  

        dst=cvCloneImage(src);  

        cvNamedWindow("Open/Close",1);  

        cvNamedWindow("Erode/Dilate",1);  

        open_close_pos = erode_dilate_pos = max_iters;  

        cvCreateTrackbar("iterations","Open/Close",&open_close_pos,max_iters*2+1,OpenClose);  

        cvCreateTrackbar("iterations","Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate);  

        for (;;)  

        {  

            int c;  

            OpenClose(open_close_pos);  

            ErodeDilate(erode_dilate_pos);  

            c= cvWaitKey(0);  

            if (c==27)  

            {  

                break;  

            }  

            switch(c) {  

            case 'e':  

                element_shape=CV_SHAPE_ELLIPSE;  

                break;  

            case 'r':  

                element_shape=CV_SHAPE_RECT;  

                break;  

            case '/r':  

                element_shape=(element_shape+1)%3;  

                break;  

            default:  

                break;   

            }  

        }  

        cvReleaseImage(&src);  

        cvReleaseImage(&dst);  

         

        cvDestroyWindow("Open/Close");  

        cvDestroyWindow("Erode/Dilate");  

        return 0;  

    }  

    /***************************** 

    腐蚀和膨胀,看上去好像是一对互逆的操作,实际上,这两种操作不具有互逆的关系。 

    开运算和闭运算正是依据腐蚀和膨胀的不可逆性,演变而来的。 

    先腐蚀后膨胀的过程就称为开运算。 

    闭运算是通过对腐蚀和膨胀的另一种不同次序的执行而得到的, 

    闭运算是先膨胀后腐蚀的过程,其功能是用来填充物体内细小空洞、连接邻近物体、平滑其边界, 

    同时不明显改变不明显改变其面积。 

    ******************************/ 

    2opencv实现二值图像细化

    内容参考:http://blog.csdn.net/byxdaz/archive/2010/06/02/5642669.aspx

     

               

    分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

    展开全文
  • Opencv 形态学操作

    2020-04-08 17:56:45
    形态学操作:使图像的形态发生改变的操作 目的:用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的 常用操作:膨胀、腐蚀、开操作、闭操作,梯度计算,顶帽变换,黑帽变换等 应用...
    • 形态学操作:使图像的形态发生改变的操作
    • 目的:用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的
    • 常用操作:膨胀、腐蚀、开操作、闭操作,梯度计算,顶帽变换,黑帽变换等
    • 应用场景:消除噪声、边界提取、区域填充、连通分量提取、凸壳、细化、粗化等;分割出独立的图像元素,或者图像中相邻的元素;求取图像中明显的极大值区域和极小值区域;求取图像梯度
    • kernel:每次操作的范围,有三种不同的形状:MORPH_RECT(矩形),MORPH_ELLIPSE(椭圆形), MORPH_CROSS(交叉形)
    # ksize 默认为3, anchor默认为-1,即中间元素
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,ksize=(11,11), anchor=(5, 5))
    

    MORPH_RECT:
    [[1,1,1,1,1],
    [1,1,1,1,1],
    [1,1,1,1,1],
    [1,1,1,1,1],
    [1,1,1,1,1]]
    MORPH_ELLIPSE:
    [[0,0,1,0,0],
    [1,1,1,1,1],
    [1,1,1,1,1],
    [1,1,1,1,1],
    [0,0,1,0,0]],
    MORPH_CROSS:
    [[0,0,1,0,0],
    [0,0,1,0,0],
    [1,1,1,1,1],
    [0,0,1,0,0],
    [0,0,1,0,0]

    以下图为例:(示例参考:OpenCV-Python教程:14.形态变换
    在这里插入图片描述

    腐蚀

    原图中的高亮区域(白色)被蚕食,效果图拥有比原图更小的高亮区域。具体操作是选择kernel范围内打最小值赋给anchor中的元素,即最小值滤波。

    # 可以执行多次,也可以自定义kernel:
    kernel = np.ones((5,5), np.uint8)
    erosion = cv2.erode(img,kernel,iterations=1) 
    

    在这里插入图片描述

    膨胀

    原理与腐蚀类似,不过是高亮区域被扩增,即最大值滤波。

    dilation = cv2.dilate(img,kernel,iterations=1)
    

    在这里插入图片描述

    开操作

    先腐蚀后膨胀,用来消除小白点,平滑较大物体的边界

    opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
    

    在这里插入图片描述

    闭操作

    先膨胀后腐蚀,用来消除白色前景中打小黑点

    closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
    

    在这里插入图片描述

    形态梯度

    可以突出团块(blob)的边缘,保留物体的边缘轮廓。实际操作是膨胀后的图像减去腐蚀后的图像

    # 下面的decrease 和 gradient结果是一样的
    kernel = np.ones((3, 3), np.uint8)
    erosion = cv2.erode(img, kernel, iterations=2)
    dilate = cv2.dilate(img, kernel, iterations=2)
    decrease = dilate - erosion 
    gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=2)
    

    在这里插入图片描述

    顶帽

    原始图像-开运算(先腐蚀再膨胀)以后的图像,突出明亮区域。可以用来提取一些小毛刺之类的图像。

    kernel = np.ones((3, 3), np.uint8)
    tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
    

    在这里插入图片描述

    黑帽

    闭运算(先膨胀再腐蚀)后的图像 - 原始图像,突出较暗区域

    kernel = np.ones((3, 3), np.uint8)
    blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
    

    在这里插入图片描述

    展开全文
  • opencv形态学操作

    2018-04-11 20:42:05
    opencv2\opencv.hpp&gt;#include &lt;iostream&gt;using namespace std;using namespace cv;int main(int argc, char** atgv){ Mat src = imread("lena.jpg"); if (src.empty()){ cout &...
    #include<opencv2\opencv.hpp>
    
    #include <iostream>
    using namespace std;
    using namespace cv;


    int main(int argc, char** atgv){
    Mat src = imread("lena.jpg");
    if (src.empty()){
    cout << "没有找到图片" << endl;
    return -1;
    }
    namedWindow("原图", CV_WINDOW_NORMAL);
    imshow("原图", src);
    Mat dst;
    Mat kernel = getStructuringElement(MORPH_RECT, Size(13, 13), Point(-1, -1));
    morphologyEx(src, dst, CV_MOP_BLACKHAT,kernel); // 形态学闭操作,去掉黑点。对二值图效果好
    //开操作是去掉白点
    //morphologyEx(src, dst, CV_MOP_GRADIENT, kernel);  //形态学梯度,对彩色图效果好
    namedWindow("形态学", CV_WINDOW_NORMAL);
    imshow("形态学",dst);


    waitKey(0);
    return 0;
    }
    展开全文
  • opencv形态学操作概念,开操作、闭操作、梯度操作、顶帽和黑帽原理和接口使用详解,此工程是各接口Demo与注释详解,欢迎下载学习使用
  • opencv形态学操作应用提取水平和垂直线.rtf
  • opencv形态学操作函数morphologyEx 2017年07月20日 18:19:45 此人小白一枚 阅读数:1001 标签: opencv 更多 个人分类: opencv 版权声明:本文为博主原创文章,未经博主允许不得转载。 ...

    opencv形态学操作函数morphologyEx

    2017年07月20日 18:19:45 此人小白一枚 阅读数:1001 标签: opencv 更多

    个人分类: opencv

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangjiao4726/article/details/75571014

    void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), intiterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )

    函数形式:

     

    函数参数:

     

    • 第一个参数,输入图像
    • 第二个参数,输出图像
    • 第三个参数,使用的形态学方法即:
    •                     MORPH_OPEN – 开运算(Opening operation)

      开运算是对图像先腐蚀再膨胀,可以排除小团的物体转换公式为:

    •                     MORPH_CLOSE – 闭运算(Closing operation)
    • 闭运算是对图像先膨胀再腐蚀,可以排除小型黑洞,变换的公式:

    •                     MORPH_GRADIENT -形态学梯度(Morphological gradient)

      返回图片为膨胀图与腐蚀图之差,可以保留物体的边缘轮廓,变换公式为:

    •                     MORPH_TOPHAT - “顶帽”(“Top hat”)
    • 返回图像为原图像与开运算结果图之差,变换公式:

    •                     MORPH_BLACKHAT - “黑帽”(“Black hat“)

      返回图片为闭运算结果图与原图像之差,变换公式为:

    • 第四个参数,InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。如果设置5*5的即:Mat(5, 5, CV_8U)
    • 第五个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
    • 第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
    • 第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
    • 第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,485
精华内容 2,994
关键字:

opencv形态学操作