1. 膨胀与腐蚀的原理

膨胀与腐蚀是数学形态学在图像处理中最基础的操作。在笔者之前的文章《图像的卷积(滤波)运算(一)——图像梯度》《图像的卷积(滤波)运算(二)——高斯滤波》具体介绍了图像卷积\滤波的具体的概念与操作,图像的膨胀与腐蚀其实也是一种类似的卷积操作。其卷积操作非常简单,对于图像的每个像素,取其一定的邻域,计算最大值/最小值作为新图像对应像素位置的像素值。其中,取最大值就是膨胀,取最小值就是腐蚀。

2. 膨胀的具体实现

1) OpenCV实现

在OpenCV中实现了图像膨胀的函数dilate(),可以直接调用:

Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
} //OpenCV方法
Mat dilated_cv;
dilate(img, dilated_cv, Mat());

dilate()函数第一个参数表示输入影像,第二个参数表示输出影像,第三个表示一个默认的核,在3X3的范围内寻找最大值。

2) C/C++实现

在一般的图像处理时,图像读写是由专门的组件进行读取的。这这里仍然使用OpenCV进行读取,以免增加复杂性。而在CV::Mat类中,提供了at()函数访问某一行某一列的像素值,可以通过at()函数去访问每一个像素的领域。

与之前OpenCV实现的一样,对于每一个像素,遍历以其像素位置为中心的3X3邻域,取最大值作为新图像对应位置的像素值。

其具体实现如下:

//从文件中读取成灰度图像
const char* imagename = "D:\\Data\\imgDemo\\lena.jpg";
Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
} //自定义方法
Mat dilated_my;
dilated_my.create(img.rows, img.cols, CV_8UC1);
for (int i = 0; i < img.rows; ++i)
{
for (int j = 0; j < img.cols; ++j)
{
//uchar minV = 255;
uchar maxV = 0; //遍历周围最大像素值
for (int yi = i-1; yi <= i+1; yi++)
{
for (int xi = j-1; xi <= j+1; xi++)
{
if (xi<0||xi>= img.cols|| yi<0 || yi >= img.rows)
{
continue;
}
//minV = (std::min<uchar>)(minV, img.at<uchar>(yi, xi));
maxV = (std::max<uchar>)(maxV, img.at<uchar>(yi, xi));
}
}
dilated_my.at<uchar>(i, j) = maxV;
}
}

3) 验证与结果

为了验证自己的算法是否正确,可以通过把两者膨胀的结果通过compare()函数进行比较。compare()函数会逐个比较两者的像素值,如果相同就会返回255(白色),如果不相同就会返回0(黑色)。整个过程的具体实现如下:

#include <iostream>
#include <algorithm>
#include <opencv2\opencv.hpp> using namespace cv;
using namespace std; int main()
{
//从文件中读取成灰度图像
const char* imagename = "D:\\Data\\imgDemo\\lena.jpg";
Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
} //OpenCV方法
Mat dilated_cv;
dilate(img, dilated_cv, Mat()); //自定义方法
Mat dilated_my;
dilated_my.create(img.rows, img.cols, CV_8UC1);
for (int i = 0; i < img.rows; ++i)
{
for (int j = 0; j < img.cols; ++j)
{
//uchar minV = 255;
uchar maxV = 0; //遍历周围最大像素值
for (int yi = i-1; yi <= i+1; yi++)
{
for (int xi = j-1; xi <= j+1; xi++)
{
if (xi<0||xi>= img.cols|| yi<0 || yi >= img.rows)
{
continue;
}
//minV = (std::min<uchar>)(minV, img.at<uchar>(yi, xi));
maxV = (std::max<uchar>)(maxV, img.at<uchar>(yi, xi));
}
}
dilated_my.at<uchar>(i, j) = maxV;
}
} //比较两者的结果
Mat c;
compare(dilated_cv, dilated_my, c, CMP_EQ); //显示
imshow("原始", img);
imshow("膨胀_cv", dilated_cv);
imshow("膨胀_my", dilated_my);
imshow("比较结果", c); waitKey(); return 0;
}

其运行结果如下所示。可以发现最后的比较结果是一张白色的图像,说明自己实现的算法是正确的。

3. 腐蚀的具体实现

同样的办法可以实现图像腐蚀的过程,只要将求局部最大值改成局部最小值就可以了。具体实现过程如下:

#include <iostream>
#include <algorithm>
#include <opencv2\opencv.hpp> using namespace cv;
using namespace std; int main()
{
//从文件中读取成灰度图像
const char* imagename = "D:\\Data\\imgDemo\\lena.jpg";
Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
} //OpenCV方法
Mat eroded_cv;
erode(img, eroded_cv, Mat()); //自定义方法
Mat eroded_my;
eroded_my.create(img.cols, img.rows, CV_8UC1);
for (int i = 0; i < img.rows; ++i)
{
for (int j = 0; j < img.cols; ++j)
{
uchar minV = 255;
//uchar maxV = 0; //遍历周围最大像素值
for (int yi = i-1; yi <= i+1; yi++)
{
for (int xi = j-1; xi <= j+1; xi++)
{
if (xi<0||xi>= img.cols|| yi<0 || yi >= img.rows)
{
continue;
}
minV = (std::min<uchar>)(minV, img.at<uchar>(yi, xi));
//maxV = (std::max<uchar>)(maxV, img.at<uchar>(yi, xi));
}
}
eroded_my.at<uchar>(i, j) = minV;
}
} //比较两者的结果
Mat c;
compare(eroded_cv, eroded_my, c, CMP_EQ); //显示
imshow("原始", img);
imshow("膨胀_cv", eroded_cv);
imshow("膨胀_my", eroded_my);
imshow("比较结果", c); waitKey(); return 0;
}

其运行结果如下:

图像的膨胀与腐蚀——OpenCV与C++的具体实现的更多相关文章

  1. Atitit 图像处理—图像形态学(膨胀与腐蚀)

    Atitit 图像处理-图像形态学(膨胀与腐蚀) 1.1. 膨胀与腐蚀1 1.2. 图像处理之二值膨胀及应用2 1.3. 测试原理,可以给一个5*5pic,测试膨胀算法5 1.4. Photoshop ...

  2. 膨胀和腐蚀 - cvErode() 和 cvDilate() 函数实现

    前言 膨胀就是对图中的每个像素取其核范围内最大的那个值,腐蚀就相反.这两个操作常用来突出显示图的某个高亮部分或者昏暗部分以及去噪.本文展示两个分别对图像进行膨胀和腐蚀的例子. 膨胀和腐蚀函数 cvEr ...

  3. OpenCV膨胀与腐蚀

    膨胀与腐蚀 本篇博客主要介绍使用OpenCV中的函数接口实现对一个图片的腐蚀或者膨胀,听起来有点像是对图像进行放大和缩小的意思,如果你也是这样认为,那我只能说你跟我一样肤浅!!在OpenCV中几乎所有 ...

  4. opencv之膨胀与腐蚀

    腐蚀和膨胀 Erosion/Dilation erosion/dilation,用白话说,就是让图像亮的区域收缩和扩张. 原理 我们定义一个卷积核矩阵.这个矩阵可以是任何形状的,但通常而言,是矩形或者 ...

  5. OpenCV——图像处理入门:膨胀与腐蚀、图像模糊、边缘检测

    全部外部依赖项: opencv_aruco341d.lib opencv_bgsegm341d.lib opencv_calib3d341d.lib opencv_bioinspired341d.li ...

  6. OpenCV膨胀和腐蚀示例代码

    #include<cv.h> #include<highgui.h> int main(int argc, char** argv) { IplImage* img = cvL ...

  7. 学习 opencv---(9)形态学图像处理(一):膨胀和腐蚀

    本篇文章中,我们一起探究了图像处理中,最基本的形态学运算--膨胀与腐蚀.浅墨在文章开头友情提醒,用人物照片做腐蚀和膨胀的素材图片得到的效果会比较惊悚,毁三观的,不建议尝试.......... 一.理论 ...

  8. paper 76:膨胀、腐蚀、开、闭运算——数字图像处理中的形态学

    膨胀.腐蚀.开.闭运算是数学形态学最基本的变换.本文主要针对二值图像的形态学膨胀:把二值图像各1像素连接成分的边界扩大一层(填充边缘或0像素内部的孔):腐蚀:把二值图像各1像素连接成分的边界点去掉从而 ...

  9. 膨胀、腐蚀、开、闭(matlab实现)

    膨胀.腐蚀.开.闭运算是数学形态学最基本的变换. 本文主要针对二值图像的形态学 膨胀:把二值图像各1像素连接成分的边界扩大一层(填充边缘或0像素内部的孔): B=[0 1 0      1 1 1   ...

随机推荐

  1. .NET 平台上C#语言的基本技术点

    第一次用画图3D画的知识点,有点丑..........开始Csharp之路

  2. Redis调用的流程(新手使用)

    就用查省市为例,别人还没查就把所有都弄好,很浪费资源和时间,redis是为了存储常用的查询操作的[结果],以此来减少直接查询数据库的次数,以下内容仅供参考,请勿照抄.(如有说得不好之处,请指点.) 言 ...

  3. python 生成 1900-2100 的二十四节气文件

    [学习笔记] 转载 #!/usr/bin/python3.7# -*- coding:utf-8 -*- '''整体思路1:根据公式算出节气日期 1900 年到 2100  200 年的时间2:特殊的 ...

  4. 高淇java300集异常机制作业

    1.以下关于异常的代码的执行结果是(C ).(选择一项) 1 2 3 4 5 6 7 8 9 10 11 12 public class Test {     public static void m ...

  5. 『vue踩坑日常』 在index.html中引入静态文件不生效

    Vue日常踩坑日常 -- 在index.html中引入静态文件不生效问题 本文针对的是Vue小白,不喜勿喷,谢谢 出现该问题的标志如下 控制台warning(Resource interpreted ...

  6. 前端笔记之CSS(上)

    层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言.CSS不仅可以静态 ...

  7. css公共库——简介中超过长度显示省略号

    在简介.引言中常见:文字只有一排,超出宽度以省略号显示,像这样 实现方法:在公共库定义otw类 .otw{ overflow: hidden; text-overflow: ellipsis; whi ...

  8. SharePoint布局页创建(实战)

    分享人:广州华软 极简 一. 前言 SharePoint有母版页及布局页,母版页控制页面头部.底部,而布局页则控制页面中间内容区域.通过布局页,可以快速修改页面内容区域. SharePoint的页面布 ...

  9. Android studio简单布局之view基本属性

    本人属于自学上路,目前是在入门阶段,所以有些内容实质性比较少,请各位大佬多多包涵. 视图view的基本属性: layout_margin:定义视图与周围视图之间的空白距离 layout_padding ...

  10. Git使用详细教程(8):Git分支

    目录 创建分支 查看分支 切换分支 删除分支 分支合并 探寻分支本质 创建分支 当我们使用git init projectName命令的时候,Git就会默认帮我们创建一个分支,名字叫做master. ...