腐蚀和膨胀 Erosion/Dilation

erosion/dilation,用白话说,就是让图像亮的区域收缩和扩张.

原理

  • 我们定义一个卷积核矩阵.这个矩阵可以是任何形状的,但通常而言,是矩形或者圆形的.同时要定义一个锚点位置.
  • 用这个卷积核矩阵挨个地划过原始图像矩阵,同时更改锚点位置的像素值.
  • 锚点位置的像素值更改为卷积核矩阵覆盖的有效像素值中的最大值/最小值(分别对应膨胀/腐蚀).

    什么叫"有效"像素值呢?就是卷积核中不为0的那些位置.用公式表达的话,即:



膨胀和腐蚀,说白了就是个求"卷积核所表示的局部"的最大值最小值的过程.

我们来看一个例子:

import cv2
import numpy as np
def test1():
img = np.zeros((10,10,1),np.uint8)
img[3:7,3:7,:] = 255
img[4:6,4:6,:] = 200 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
erosion_dst = cv2.erode(img, kernel1)
print(erosion_dst)

首先我们创建一个10 x 10的图像,像素如下:

[[  0   0   0   0   0   0   0   0   0   0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 255 255 255 255 0 0 0]
[ 0 0 0 255 200 200 255 0 0 0]
[ 0 0 0 255 200 200 255 0 0 0]
[ 0 0 0 255 255 255 255 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]]

我们创建一个卷积核:

kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))

getStructuringElement api



三个参数分别为卷积核的形状/大小/锚点位置. 默认锚点在矩阵的中心位置.

形状有三种

上面代码中我们创建的3 x 3矩形卷积核如下

用这个卷积核对原始图像做腐蚀后得到的矩阵如下

即矩阵有如下变化:

[[  0   0   0   0   0   0   0   0   0   0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 255 255 255 255 0 0 0]
[ 0 0 0 255 200 200 255 0 0 0]
[ 0 0 0 255 200 200 255 0 0 0]
[ 0 0 0 255 255 255 255 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]] --> [[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 200 200 0 0 0 0]
[ 0 0 0 0 200 200 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]]

我们考虑第三行第四列img[2,3,:]这个像素.当我们的卷积核矩阵的锚点位置与该像素重合时,我们取周边所有像素的最小值.最小值为0.所以该位置的像素值变为0. 其余位置的像素值同理可求.

我们稍微改一下我们的代码,然后再看一下不同卷积核作用下的不同结果,会理解的更清楚

import cv2
import numpy as np
def test1():
img = np.zeros((10,10,1),np.uint8)
img[3:7,3:7,:] = 255
img[4:6,4:6,:] = 200 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
print(kernel1)
erosion_dst = cv2.erode(img, kernel1)
print(erosion_dst) def test2():
img = np.zeros((10,10,1),np.uint8)
img[3:7,3:7,:] = 255
img[4:6,4:6,:] = 200
img[2,4,:] = 100 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
erosion_dst = cv2.erode(img, kernel1)
print(erosion_dst) kernel2 = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
erosion_dst2 = cv2.erode(img, kernel2)
print(erosion_dst2) test2()

我们把原始图像矩阵改为

[[  0   0   0   0   0   0   0   0   0   0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 100 0 0 0 0 0]
[ 0 0 0 255 255 255 255 0 0 0]
[ 0 0 0 255 200 200 255 0 0 0]
[ 0 0 0 255 200 200 255 0 0 0]
[ 0 0 0 255 255 255 255 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]]

用kernal1时,kernal1如下:



以第四行,第五列的像素为例,用卷积核的锚点与之对应,此时计算的是其周围八个像素的最小值,最小值为0.

所以我们得到的矩阵为

当我们用kernal2时,kernal2如下:



对第四行,第五列的像素,用卷积核的锚点与之对应,此时计算的不再是周围八个像素的最小值,而是其正上方,正下方,正左边,正右边的四个像素的最小值.该值为100.

所以我们得到的矩阵为

opencv示例

from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse erosion_size = 0
max_elem = 2
max_kernel_size = 21 title_trackbar_element_type = 'Element:\n 0: Rect \n 1: Cross \n 2: Ellipse'
title_trackbar_kernel_size = 'Kernel size:\n 2n +1'
title_erosion_window = 'Erosion Demo'
title_dilatation_window = 'Dilation Demo' def erosion(val):
erosion_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_erosion_window)
erosion_type = 0
val_type = cv.getTrackbarPos(title_trackbar_element_type, title_erosion_window)
if val_type == 0:
erosion_type = cv.MORPH_RECT
elif val_type == 1:
erosion_type = cv.MORPH_CROSS
elif val_type == 2:
erosion_type = cv.MORPH_ELLIPSE
element = cv.getStructuringElement(erosion_type, (2*erosion_size + 1, 2*erosion_size+1), (erosion_size, erosion_size))
erosion_dst = cv.erode(src, element)
cv.imshow(title_erosion_window, erosion_dst) def dilatation(val):
dilatation_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_dilatation_window)
dilatation_type = 0
val_type = cv.getTrackbarPos(title_trackbar_element_type, title_dilatation_window)
if val_type == 0:
dilatation_type = cv.MORPH_RECT
elif val_type == 1:
dilatation_type = cv.MORPH_CROSS
elif val_type == 2:
dilatation_type = cv.MORPH_ELLIPSE
element = cv.getStructuringElement(dilatation_type, (2*dilatation_size + 1, 2*dilatation_size+1), (dilatation_size, dilatation_size))
dilatation_dst = cv.dilate(src, element)
cv.imshow(title_dilatation_window, dilatation_dst) src = cv.imread("/home/sc/disk/keepgoing/opencv_test/j.png")
cv.namedWindow(title_erosion_window)
cv.createTrackbar(title_trackbar_element_type, title_erosion_window , 0, max_elem, erosion)
cv.createTrackbar(title_trackbar_kernel_size, title_erosion_window , 0, max_kernel_size, erosion) cv.namedWindow(title_dilatation_window)
cv.createTrackbar(title_trackbar_element_type, title_dilatation_window , 0, max_elem, dilatation)
cv.createTrackbar(title_trackbar_kernel_size, title_dilatation_window , 0, max_kernel_size, dilatation) erosion(0)
dilatation(0)
cv.waitKey()

通过createTrackbar在窗口上创建两个bar,方便我们看不同种类不同大小的卷积核的影响.

cv.createTrackbar(title_trackbar_element_type, title_erosion_window , 0, max_elem, erosion)
cv.createTrackbar(title_trackbar_kernel_size, title_erosion_window , 0, max_kernel_size, erosion)

原始图片:

处理效果:

opencv实现

https://github.com/opencv/opencv/blob/master/modules/imgproc/src/morph.dispatch.cpp

opencv之膨胀与腐蚀的更多相关文章

  1. opencv 形态学膨胀和腐蚀以及开运算和闭运算

  2. 图像的膨胀与腐蚀——OpenCV与C++的具体实现

    目录 1. 膨胀与腐蚀的原理 2. 膨胀的具体实现 1) OpenCV实现 2) C/C++实现 3) 验证与结果 3. 腐蚀的具体实现 1. 膨胀与腐蚀的原理 膨胀与腐蚀是数学形态学在图像处理中最基 ...

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

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

  4. OpenCV膨胀与腐蚀

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

  5. OpenCV图像处理篇之腐蚀与膨胀

    转载请注明出处:http://xiahouzuoxin.github.io/notes 腐蚀与膨胀 腐蚀和膨胀是图像的形态学处理中最主要的操作,之后遇见的开操作和闭操作都是腐蚀和膨胀操作的结合运算. ...

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

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

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

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

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

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

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

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

随机推荐

  1. CF991C Candies 二分 第十五

    Candies time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  2. 跟我学SpringCloud | 第十七篇:服务网关Zuul基于Apollo动态路由

    目录 SpringCloud系列教程 | 第十七篇:服务网关Zuul基于Apollo动态路由 Apollo概述 Apollo相比于Spring Cloud Config优势 工程实战 示例代码 Spr ...

  3. R:ggplot2数据可视化——基础知识

    1 安装 # 获取ggplot2 最容易的就是下载整个tidyverse: install.packages("tidyverse") # 也可以选择只下载ggplot2: ins ...

  4. 【Offer】[5] 【替换空格】

    题目描述 思路分析 Java代码 代码链接 题目描述 请实现一个函数,把字符串中的每个空格替换成"%20". 例如输入"We are happy.",则输出&q ...

  5. odoo12从零开始:三、2)odoo模型层

    前言 上一篇文章(创建你的第一个应用模块(module))已经大致描述了odoo的模型层(model)和视图层(view),这一篇文章,我们将系统地介绍有关于model的知识,其中包括: 1.模型的类 ...

  6. Go语言标准库之net_http

    Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现. net/http介绍 Go语言内置的net/http包提供了HTTP客户端和服务端的实现. HTTP协议 超文本传输协 ...

  7. Spring Cloud(一):服务注册与发现

    Spring Cloud是什么 Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均 ...

  8. C#中的根据实体增删改操作

    在日常操作中,我们经常会对一些数据进行批量更新, 我在使用EF的时候,没有找到比较好的批量更新的解决方案, 便参考了张占岭前辈的博客,整合了这么一个简略版的使用实体类生成数据库增删改SQL的操作类 在 ...

  9. 大数据平台搭建 - cdh5.11.1 - oozie安装

    一.简介 oozie是hadoop平台开源的工作流调度引擎,用来管理hadoop作业,属于web应用程序,由oozie server 和oozie client构成. oozie server运行与t ...

  10. Elastic Stack 笔记(四)Elasticsearch5.6 索引及文档管理

    博客地址:http://www.moonxy.com 一.前言 在 Elasticsearch 中,对文档进行索引等操作时,既可以通过 RESTful 接口进行操作,也可以通过 Java 也可以通过 ...