建议大家看看网络视频教程:http://www.opencvchina.com/thread-886-1-1.html 

 

腐蚀与膨胀都是针对灰度图的形态学操作,比如下面的一副16*16的灰度图。

它每个像素对应的值为(每个像素值范围都在0-255之间)为:

      我们定义一个5*5的结构元素,该结构元素用5*5的矩阵表示,其中为1的单元,表示该单元在结构元素中有效,另外还定义一个锚点,坐标为(2,2),在单元格中用蓝色表示。

腐蚀/膨胀的操作就是用结构元素的锚点位置对齐图像的像素,然后从左上角的第一个像素滑动到右下角的最后一个像素。

在滑动到每个像素时,结构元素中为1的各个坐标格子会与相应的像素对齐。比如滑动到第一个像素时,如下图所示:

此时,原图像中对齐的格子,如下图所示。

       腐蚀操作就是取其中的最小值,代替原素像素值,即image(0,0)的像素值为min(0,1,2,16,32)=0,而膨胀操作则相反,是取最大值代替原像素,即image(0,0)=max(0,1,2,16,32)=32。

下面我们再看一个例子,当结构元素滑动到image(4,4 ) 位置时候,图像的腐蚀膨胀操作:

      此时,结构元素对齐的像素如下图所示,对于腐蚀操作,此时image(4,4)应该等于min(36,52,66,67,68,69,70,84,100)=36,而膨胀操作,则是image(4,4)等于max(36,52,66,67,68,69,70,84,100)=100。

需要注意下面的一种情况:

结构元素如下图所示,仍是5*5的十字形状,但锚点位置在(3,3),此时当结构元素在图像中滑动时候,会有一些特殊情况需要注意。

比如滑动到图像的(0,0)位置时,结构元素中为1的单元格和图像没有交叉的格子,此时按我的理解,应该保持像素的值不变,但opencv中却不是这样,当腐蚀时,此时(0,0)位置像素值为255,当膨胀时,(0,0)位置像素值为0。

下面是我写的简单的腐蚀膨胀函数代码:

  1. cv::Mat gMophEx::Erode(cv::Mat& img, cv::Mat kernel, cv::Point anchor)
    {
    cv::Mat tmpImg;
    img.copyTo(tmpImg);
    int i, j, m, n;
    uchar* p;
    for(i=0; i<img.rows; i++)
    {
    p = tmpImg.ptr<uchar>(i);
    for(j=0; j<img.cols; j++)
    {
    int min = 100000;
    for(m = 0; m < kernel.rows; m++)
    {
    for(n=0; n <kernel.cols; n++)
    {
    if(kernel.data[m*kernel.cols+n]==1)
    {
    //printf("i=%d, j=%d, m=%d,n=%d,tt1=%d, tt2=%d, tt3=%d\n",i,j,m,n,j+n-anchor.y,i + m - anchor.x,(i + m - anchor.x)*img.cols + j+n-anchor.y);
    if(j+n-anchor.x < 0 || j+n-anchor.y >=img.cols || i + m - anchor.x < 0 || i + m - anchor.x >= img.rows)
    continue;
    //printf("%d \n",img.data[(i + m - anchor.x)*img.cols + j+n-anchor.y]);
    if(img.data[(i + m - anchor.x)*img.cols + j+n-anchor.y]<min)
    min = img.data[(i + m - anchor.x)*img.cols + j+n-anchor.y];
    }
    }
    }
  2.  
  3. if (min < 256)
    {
    p[j] = min;
    }
    else if(min==100000)
    {
    p[j] = 255; //opencv结果是这样,当腐蚀时候,当前像素找不到相应的点,赋予最大值
    }
  4.  
  5. }
    }
    return tmpImg;
    }
  6.  
  7. cv::Mat gMophEx::Dilate(cv::Mat& img, cv::Mat kernel, cv::Point anchor)
    {
    cv::Mat tmpImg;
    img.copyTo(tmpImg);
    int i, j, m, n;
    uchar* p;
    for(i=0; i<img.rows; i++)
    {
    p = tmpImg.ptr<uchar>(i);
    for(j=0; j<img.cols; j++)
    {
    int max=-1;
    for(m = 0; m < kernel.rows; m++)
    {
    for(n=0; n <kernel.cols; n++)
    {
    if(kernel.data[m*kernel.cols+n]==1)
    {
    //printf("i=%d, j=%d, m=%d,n=%d, tt=%d\n",i,j,m,n,(i + m - anchor.x)*img.cols + j+n-anchor.y);
    if(j+n-anchor.y < 0 || j+n-anchor.y >=img.cols || i + m - anchor.x < 0 || i + m - anchor.x >= img.rows)
    continue;
    //printf("%d \n",img.data[(i + m - anchor.x)*img.cols + j+n-anchor.y]);
    if(img.data[(i + m - anchor.x)*img.cols + j+n-anchor.y]>max)
    max = img.data[(i + m - anchor.x)*img.cols + j+n-anchor.y];
    }
    }
    }
  8.  
  9. if (max >= 0)
    {
    p[j] = max;
    }
    else if(max == -1)
    {
    p[j] = 0;
    }
    //PrintMat(tmpImg);
    }
    }
    return tmpImg;
    }

最后我们对图像进行腐蚀操作,得到新的图像像素值为:

膨胀操作后的像素值为:

程序代码: 工程FirstOpenCV4

OpenCV学习(10) 图像的腐蚀与膨胀(1)的更多相关文章

  1. OpenCV学习笔记——图像的腐蚀与膨胀

    顺便又复习了一下cvcopy如何进行图像拼接(最近觉得打开多幅图像分别看不如缩小掉放拼接到一幅图像上对比来的好) 首先把拼接的目标图像设置兴趣区域ROI,比如我有一个total,要把a.b.c分别从左 ...

  2. OpenCV学习(11) 图像的腐蚀与膨胀(2)

    先对一副灰度图像进行腐蚀操作,然后在腐蚀后的图像上再进行膨胀操作,我们定义这个操作为开操作. 先对一副图像进行膨胀操作,然后在膨胀后的图像上再进行腐蚀操作,我们定义这个操作为闭操作.       开操 ...

  3. OpenCV学习(12) 图像的腐蚀与膨胀(3)

    通过使用不同的结构元素来进行膨胀腐蚀操作,可以检测图像中的角点,下面就一步一步看这个算法如果实现角点检测. 原图像: 首先我们创建四个结构元素 先用十字结构元素对原图像进行膨胀操作,得到下面的图像 再 ...

  4. opencv:图像的腐蚀和膨胀

    1.图像的腐蚀 图像的腐蚀和膨胀都是相对于像素值高(白色方向)说的,腐蚀简单的说就是白色”被腐蚀“了,也就是像素值低(黑色方向)的变多,白色变少. 腐蚀的原理是利用一个内核对图像进行卷积(扫描),内核 ...

  5. c#数字图像处理(十二)图像的腐蚀与膨胀

    背景知识 腐蚀与膨胀基本原理:就是用一个特定的结构元素来与待处理图像按像素做逻辑操作:可以理解成拿一个带孔的网格板(结构元素矩阵中元素为1的为孔)盖住图像的某一部分,然后按照各种不同的观察方式来确定操 ...

  6. opencv中的图像形态学——腐蚀膨胀

    腐蚀膨胀是图像形态学比较常见的处理,腐蚀一般可以用来消除噪点,分割出独立的图像元素等. 一般腐蚀操作对二值图进行处理,腐蚀操作如下图,中心位置的像素点是否与周围领域的像素点颜色一样(即是否是白色点,即 ...

  7. opencv学习(六)——图像基本操作

    图像基本操作 一.访问和修改像素值 先来理解一下,图像与一般的矩阵或张量有何不同(不考虑图像的格式,元数据等信息).首先,一张图像有自己的属性,宽,高,通道数.其中宽和高是我们肉眼可见的属性,而通道数 ...

  8. opencv学习笔记-图像对比度、亮度调节

    在数学中我们学过线性理论,在图像亮度和对比度调节中同样适用,看下面这个公式: 在图像像素中其中: 参数f(x)表示源图像像素. 参数g(x) 表示输出图像像素. 参数a(需要满足a>0)被称为增 ...

  9. opencv学习笔记-图像叠加、混合

    在图像处理中,目标区域定义为感兴趣区域ROI(region of Interest),这是后期图像处理的基础,在获取ROI后,进行一些列的处理.ROI区域在Opencv中就是Rect,先构建Rect, ...

随机推荐

  1. git用法大全

    转载自实验楼,之前有更新过两篇git的文章,毕竟内容太少,而git还有很多更丰富的技能,在实验楼上有一系列全的教程,这里做一下备案.需要时查阅. Git 实战教程 目录 一.实验说明 二.git的初始 ...

  2. javascript右下角弹层及自动隐藏

    在编写项目中总会需要有个右下角弹层提示公告的需求,怎么用更简单方面,更简洁代码,实现更好用户体验这个就是我们的所要做的内容.市场这块弹层很多,但功能不尽如人意.下面分享早些时候自己编写,以及现在还在应 ...

  3. REST API 支持方式

    1.JSONPlaceholder 是一个提供免费的在线 REST API 的网站,我们在开发时可以使用它提供的 url 地址测试下网络请求以及请求参数.或者当我们程序需要获取一些假数据.假图片时也可 ...

  4. Django实现单用户登录

    最近由于要毕业了写论文做毕设,然后还在实习发现已经好久都没有写博客了.今天由于工作需求,需要用Django实现单用户登录.大概意思就是跟QQ一样的效果,每个账号只能一个地方登录使用,限制账号的登录次数 ...

  5. 网络流—最大流(Edmond-Karp算法)

    一.含义 从源点到经过的所有路径的最终到达汇点的所有流量和 例如: 在这个图中求源点1,到汇点4的最大流.答案为50,其中1->2->4为20 :1->4为20 :1->2-& ...

  6. hihocoder #1071 : 小玩具

    闻所未闻的$dp$神题(我不会的题) 令$f[S][i]$表示子集状态为$S$,且$S$中最大联通块恰好为$i$的方案数 考虑转移,我们枚举$S$中最小的元素$v$来转移,这样就能不重 $f[S][i ...

  7. 【期望DP】BZOJ3450- Tyvj1952 Easy

    ---恢复内容开始--- [题目大意] 有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a个comb就有a*a分,comb就是极大的连续o.求期望分数. [思路] 比之前的OS ...

  8. 《深入理解Spark-核心思想与源码分析》(五)第五章任务提交与执行

    即欲捭之贵周,即欲阖之贵密.周密之贵,微而与道相随.---<鬼谷子> 解释:译文:如果要分析问题,关键在于周详,如果要综合归纳问题,关键在于严密.周详严密的关键在于精深而与道相随. 解词: ...

  9. request.getScheme() 取到https正确的协议(转载)

    最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https协议 但是,明明是https url请求,发现 log里 ...

  10. Codeforces Round #299 (Div. 2) B. Tavas and SaDDas 水题

    B. Tavas and SaDDas Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/535/p ...