• 形态学操作就是基于形状的一系列图像处理操作。通过将 结构元素 作用于输入图像来产生输出图像。

  • 最基本的形态学操作有二:腐蚀与膨胀(Erosion 与 Dilation)。 他们的运用广泛:

    • 消除噪声
    • 分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
    • 寻找图像中的明显的极大值区域或极小值区域。
  • 通过以下图像,我们简要来讨论一下膨胀与腐蚀操作(译者注:注意这张图像中的字母为黑色,背景为白色,而不是一般意义的背景为黑色,前景为白色):

膨胀

  • 此操作将图像  与任意形状的内核 (),通常为正方形或圆形,进行卷积。

  • 内核  有一个可定义的 锚点, 通常定义为内核中心点。

  • 进行膨胀操作时,将内核  划过图像,将内核  覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )。对上图采用膨胀操作我们得到:

背景(白色)膨胀,而黑色字母缩小了。

腐蚀

  • 腐蚀在形态学操作家族里是膨胀操作的孪生姐妹。它提取的是内核覆盖下的相素最小值。

  • 进行腐蚀操作时,将内核  划过图像,将内核  覆盖区域的最小相素值提取,并代替锚点位置的相素。

  • 以与膨胀相同的图像作为样本,我们使用腐蚀操作。从下面的结果图我们看到亮区(背景)变细,而黑色区域(字母)则变大了。

源码

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>using namespace cv;/// 全局变量
Mat src, erosion_dst, dilation_dst;int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;/** Function Headers */
void Erosion( int, void* );
void Dilation( int, void* );/** @function main */
int main( int argc, char** argv )
{/// Load 图像src = imread( argv[1] );if( !src.data ){ return -1; }/// 创建显示窗口namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );cvMoveWindow( "Dilation Demo", src.cols, 0 );/// 创建腐蚀 TrackbarcreateTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",&erosion_elem, max_elem,Erosion );createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",&erosion_size, max_kernel_size,Erosion );/// 创建膨胀 TrackbarcreateTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",&dilation_elem, max_elem,Dilation );createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",&dilation_size, max_kernel_size,Dilation );/// Default startErosion( 0, 0 );Dilation( 0, 0 );waitKey(0);return 0;
}/**  @function Erosion  */
void Erosion( int, void* )
{int erosion_type;if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( erosion_type,Size( 2*erosion_size + 1, 2*erosion_size+1 ),Point( erosion_size, erosion_size ) );/// 腐蚀操作erode( src, erosion_dst, element );imshow( "Erosion Demo", erosion_dst );
}/** @function Dilation */
void Dilation( int, void* )
{int dilation_type;if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( dilation_type,Size( 2*dilation_size + 1, 2*dilation_size+1 ),Point( dilation_size, dilation_size ) );///膨胀操作dilate( src, dilation_dst, element );imshow( "Dilation Demo", dilation_dst );
}

解释

  1. 大部分代码应该不需要解释了。

    • 装载图像 (可以是 RGB图像或者灰度图 )
    • 创建两个显示窗口 (一个用于膨胀输出,一个用于腐蚀输出)
    • 为每个操作创建两个 Trackbars:
      • 第一个 trackbar “Element” 返回 erosion_elem 或者 dilation_elem
      • 第二个 trackbar “Kernel size” 返回 erosion_size 或者 dilation_size 。
    • 每次移动标尺, 用户函数 Erosion 或者 Dilation 就会被调用,函数将根据当前的trackbar位置更新输出图像。

    让我们分析一下这两个函数:

  2. Erosion:

    /**  @function Erosion  */
    void Erosion( int, void* )
    {int erosion_type;if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( erosion_type,Size( 2*erosion_size + 1, 2*erosion_size+1 ),Point( erosion_size, erosion_size ) );/// 腐蚀操作erode( src, erosion_dst, element );imshow( "Erosion Demo", erosion_dst );
    }
    

    • 进行 腐蚀 操作的函数是 erode 。 它接受了三个参数:

      • src: 原图像

      • erosion_dst: 输出图像

      • element: 腐蚀操作的内核。 如果不指定,默认为一个简单的  矩阵。否则,我们就要明确指定它的形状,可以使用函数getStructuringElement:

        Mat element = getStructuringElement( erosion_type,Size( 2*erosion_size + 1, 2*erosion_size+1 ),Point( erosion_size, erosion_size ) );
        

      我们可以为我们的内核选择三种形状之一:

      • 矩形: MORPH_RECT
      • 交叉形: MORPH_CROSS
      • 椭圆形: MORPH_ELLIPSE

      然后,我们还需要指定内核大小,以及 锚点 位置。不指定锚点位置,则默认锚点在内核中心位置。

    • 就这些了,我们现在可以对图像进行腐蚀操作了。

    Note

    OpenCV的 erode 函数还有另外的参数,其中一个参数允许你一下对图像进行多次腐蚀操作。在这个简单的文档中没有用到它,但是你可以参考OpenCV的使用手册。

  3. Dilation:

下面是膨胀的代码,你可以看到,它和 Erosion 函数是多么相似。 这里我们同样可以指定内核的形状,锚点和大小。

/** @function Dilation */
void Dilation( int, void* )
{int dilation_type;if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }Mat element = getStructuringElement( dilation_type,Size( 2*dilation_size + 1, 2*dilation_size+1 ),Point( dilation_size, dilation_size ) );/// 膨胀操作dilate( src, dilation_dst, element );imshow( "Dilation Demo", dilation_dst );
}

opencv 图像的腐蚀与膨胀相关推荐

  1. 详解图像形态学操作之图形的腐蚀和膨胀的概念和运算过程,并利用OpenCV的函数erode()和函数dilate()对图像进行腐蚀和膨胀操作

    图像形态学中两种最基本的操作就是对图形的腐蚀和膨胀,可以说,形态学中的中高级操作都是建立在这两种操作之上.通过这两种基本的运算可以去除图像中的噪声,分割出独立的区域或者将两个区域连接在一起. 关于图像 ...

  2. cuda学习笔记5——CUDA实现图像形态学腐蚀、膨胀

    cuda学习笔记5--CUDA实现图像形态学腐蚀.膨胀 代码 linux如何编译cuda和opencv代码 耗时情况 代码 #include "cuda_runtime.h" #i ...

  3. 简单说说我理解的图像的腐蚀和膨胀

    写这篇文章的时候在想办法搞opencv,看着课上教的莫名其妙,直接给我整不会了,借此机会记下来怎么腐蚀和膨胀 腐蚀 这里借一下图,原帖(5条消息) 图像的腐蚀与膨胀_张齐贤的博客-CSDN博客_腐蚀膨 ...

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

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

  5. matlab图像的腐蚀和膨胀_OpenCV图像处理系列八 --- 腐蚀与膨胀

    今天,我们一起来学习图像形态学操作中两种最基本的形态学操作,即腐蚀与膨胀. 一.理论 数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数 ...

  6. pytorch实现图像的腐蚀和膨胀

    前言: 之所以想到用 pytorch ,主要是因为不想在网络模块中调用 opencv 的函数. 调用 opencv 函数的基本步骤如下:先把 pytorch 的 tensor 转到 cpu 上,然后转 ...

  7. opencv中的腐蚀与膨胀(转)

    图像腐蚀和图像膨胀是图像中两种最基本形态学操作. void erode( const Mat& src, Mat& dst, const Mat& element,Point ...

  8. opengl对图像进行腐蚀和膨胀

    效果图 膨胀的原理: 膨胀就是求局部最大值的操作,就是给定一个核对图像进行卷积操作,见下图 将核B与图像A卷积,即计算B覆盖区域的像素点的最大值,并把这个最大值赋给参考点指定的像素,这样 就会使图像中 ...

  9. opencv python 图片腐蚀和膨胀

    参考:http://blog.csdn.net/yellow_red_people/article/details/53181239 定义一个5x5的结构:kernel=np.uint8(np.zer ...

最新文章

  1. Docker架构、镜像及容器的安装和基本操作
  2. php ci nginx 伪静态rewrite配置方法
  3. excel重复上一步快捷键_初学Excel办公软件重复上次的操作
  4. 更改mysql最大连接数
  5. windows下的diskpart指令彻底格式化清除U盘
  6. python循环输出三角形图案的画_python循环输出三角形图案的例子
  7. php 函数 数组 难学,php 数组的常用函数
  8. zabbix计算型监控项函数last_面试官:如何用zabbix实现监控linux服务器进程使用率...
  9. HDFS 中常见的Timeout
  10. matlab设计一个简单图像直方图均衡的GUI程序
  11. demo 网络运维_【运维面试】面试官:你们公司的docker主要用来做啥?
  12. [HNOI2006]最短母串问题 --- AC自动机 + 隐式图搜索
  13. pandas dataframe遍历_Pandas循环提速7万多倍!Python数据分析攻略!
  14. mysql 超时异常捕获_Mysql的链接超时异常CommunicationsException
  15. PHP has encountered an Access Violation at
  16. 可以获得高排名的B2B平台大全
  17. 相似图片搜索算法介绍
  18. 如何让企业微信的消息在微信里显示?
  19. Qt 5.7 亮瞎眼的更新
  20. Arduino使用火焰传感器

热门文章

  1. Atheros AR9485 ubuntu 10.04 驱动安装及networking disable问题解决
  2. 使用GPRS模块进行TCP/UDP连接的过程分析
  3. PYTHON学习0022:函数基本介绍----2019-6-17
  4. Java并发编程:AbstractQueuedSynchronizer的内部结构
  5. 多个表关联的查询语句
  6. EntityFramework之摸索EF底层(八)
  7. wpa_supplicant与kernel的接口
  8. vc判断文件夹是否存在
  9. 基于动态用户偏好和服务质量的推荐算法
  10. version `ZLIB_1.2.3.4' not found 解决方法