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. uni-app—从安装到卸载

    uni-app实现了一套代码,同时运行到多个平台.支持iOS模拟器.Android模拟器.H5.微信开发者工具.支付宝小程序Studio.百度开发者工具.字节跳动开发者工具 工具安装 开发uni-ap ...

  2. DDL(数据定义语言)

    1.Oracle中常见的数据类型分类:(A) 1.number(x,y) 数字类型,x表示最大长度,y表示精度对应java中除char外所有基本数据类型(byte.short.int.long.flo ...

  3. MD5加密Util

    目录 (1)需要导入的包 (2)MD5Util类 (3)使用举例 (1)需要导入的包 <dependency> <groupId>org.apache.commons</ ...

  4. jqgrid postData post方式累加参数,缓存了原来的数据

    今天做项目的时候发现一个问题,我们有一个筛选项,一个是VIP用户,一个是普通用户,还有一个是全部用户,首先看下我们的selection <select name="" id= ...

  5. 第一次JVM分析记录:Out of Memory Error (workgroup.cpp:96), pid=6196, tid=139999645685504

    tomcat的catalina.out日志报错如下: Exception in thread "http-bio-8081-Acceptor-0" java.lang.OutOfM ...

  6. 【原】无脑操作:ElasticSearch学习笔记(01)

    开篇来自于经典的“保安的哲学三问”(你是谁,在哪儿,要干嘛) 问题一.ElasticSearch是什么?有什么用处? 答:截至2018年12月28日,从ElasticSearch官网(https:// ...

  7. redis缓存类

    <?php class Redis_model{ public $redis = null; public function __construct() { $hosts = $this-> ...

  8. 跨平台数据库工具Azure Data Studio

    Azure Data Studio是一种跨平台数据库工具,适用于在Windows,MacOS和Linux上使用Microsoft系列内部部署和云数据平台的数据专业人员.Azure Data Studi ...

  9. 使用WSL吧

    WSL(Windows Subsystem for Linux)已经装在电脑上好一阵子了,谁如果还没装的,可以看看本文,至少知道个大概,觉得有用的话知道该如何做. 简介 WSL简单说就是一个能让你在W ...

  10. python --- 冒泡排序算法

    别想太多了,这个冒泡排序就是我们脑海中想到的那个冒泡,就好像是气泡一样,较小的元素比较轻,从而要往上浮出来, 冒泡排序算法. 要对‘气泡’序列处理若干遍.所谓一遍处理,就是自底向上检查一遍这个序列,并 ...