OpenCV学习(10) 图像的腐蚀与膨胀(1)
建议大家看看网络视频教程: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。
下面是我写的简单的腐蚀膨胀函数代码:
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];
}
}
} if (min < 256)
{
p[j] = min;
}
else if(min==100000)
{
p[j] = 255; //opencv结果是这样,当腐蚀时候,当前像素找不到相应的点,赋予最大值
} }
}
return tmpImg;
} 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];
}
}
} if (max >= 0)
{
p[j] = max;
}
else if(max == -1)
{
p[j] = 0;
}
//PrintMat(tmpImg);
}
}
return tmpImg;
}
最后我们对图像进行腐蚀操作,得到新的图像像素值为:
膨胀操作后的像素值为:

程序代码: 工程FirstOpenCV4
OpenCV学习(10) 图像的腐蚀与膨胀(1)的更多相关文章
- OpenCV学习笔记——图像的腐蚀与膨胀
顺便又复习了一下cvcopy如何进行图像拼接(最近觉得打开多幅图像分别看不如缩小掉放拼接到一幅图像上对比来的好) 首先把拼接的目标图像设置兴趣区域ROI,比如我有一个total,要把a.b.c分别从左 ...
- OpenCV学习(11) 图像的腐蚀与膨胀(2)
先对一副灰度图像进行腐蚀操作,然后在腐蚀后的图像上再进行膨胀操作,我们定义这个操作为开操作. 先对一副图像进行膨胀操作,然后在膨胀后的图像上再进行腐蚀操作,我们定义这个操作为闭操作. 开操 ...
- OpenCV学习(12) 图像的腐蚀与膨胀(3)
通过使用不同的结构元素来进行膨胀腐蚀操作,可以检测图像中的角点,下面就一步一步看这个算法如果实现角点检测. 原图像: 首先我们创建四个结构元素 先用十字结构元素对原图像进行膨胀操作,得到下面的图像 再 ...
- opencv:图像的腐蚀和膨胀
1.图像的腐蚀 图像的腐蚀和膨胀都是相对于像素值高(白色方向)说的,腐蚀简单的说就是白色”被腐蚀“了,也就是像素值低(黑色方向)的变多,白色变少. 腐蚀的原理是利用一个内核对图像进行卷积(扫描),内核 ...
- c#数字图像处理(十二)图像的腐蚀与膨胀
背景知识 腐蚀与膨胀基本原理:就是用一个特定的结构元素来与待处理图像按像素做逻辑操作:可以理解成拿一个带孔的网格板(结构元素矩阵中元素为1的为孔)盖住图像的某一部分,然后按照各种不同的观察方式来确定操 ...
- opencv中的图像形态学——腐蚀膨胀
腐蚀膨胀是图像形态学比较常见的处理,腐蚀一般可以用来消除噪点,分割出独立的图像元素等. 一般腐蚀操作对二值图进行处理,腐蚀操作如下图,中心位置的像素点是否与周围领域的像素点颜色一样(即是否是白色点,即 ...
- opencv学习(六)——图像基本操作
图像基本操作 一.访问和修改像素值 先来理解一下,图像与一般的矩阵或张量有何不同(不考虑图像的格式,元数据等信息).首先,一张图像有自己的属性,宽,高,通道数.其中宽和高是我们肉眼可见的属性,而通道数 ...
- opencv学习笔记-图像对比度、亮度调节
在数学中我们学过线性理论,在图像亮度和对比度调节中同样适用,看下面这个公式: 在图像像素中其中: 参数f(x)表示源图像像素. 参数g(x) 表示输出图像像素. 参数a(需要满足a>0)被称为增 ...
- opencv学习笔记-图像叠加、混合
在图像处理中,目标区域定义为感兴趣区域ROI(region of Interest),这是后期图像处理的基础,在获取ROI后,进行一些列的处理.ROI区域在Opencv中就是Rect,先构建Rect, ...
随机推荐
- SGU 209. Areas
209. Areas time limit per test: 0.25 sec.memory limit per test: 65536 KB input: standardoutput: stan ...
- 查找无序数组中第K大的数
思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> # ...
- 2017年浙江工业大学大学生程序设计迎新赛预赛 H - 栗酱的文明
题目描述 “伟大的勇士兔栽栗女王,所有栗子看到您都不寒而栗,但也非常尊重您.您骑着威风凛凛的小白兔,带领兔栽栗们奋勇前行.伟大史诗告诉我们,烈兔勇栗从大草原飞奔出来,冲在每场战争的前线 ...
- AM335x开发板与PC机虚拟机建立tftp文件传输
1.AM335x开发板必须要支持以太网,而且在U-boot中要有完好的以太网驱动 因为开发板的储存介质为SD卡,所以在编译好的U-boot中并没有配置网络环境,为了不使每次上电都修改u-boot的网络 ...
- 【Java】SpringBoot入门学习及基本使用
SpringBoot入门及基本使用 SpringBoot的介绍我就不多说了,核心的就是"约定大于配置",接下来直接上干货吧! 本文的实例: github-LPCloud,欢迎sta ...
- 虚拟环境中pip install requirments.txt: Cannot fetch index base URL https://pypi.python.org/simple/
Stackoverflow : http://stackoverflow.com/questions/15501133/python-pip-error-cannot-fetch-index-bas ...
- nyoj 作业题 dp
作业题 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程, ...
- property staticmathod classmethod 反射
使用@property 在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻 ...
- 【BZOJ 2654】 MST
2654: tree Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示 ...
- stl upper_bound()
http://blog.csdn.net/niushuai666/article/details/6734650 upper_bound( a , b , k )返回有序升序序列[a,b)中能放下 ...




