腐蚀和膨胀 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. R:ggplot2数据可视化——进阶(1)

    ,分为三个部分,此篇为Part1,推荐学习一些基础知识后阅读~ Part 1: Introduction to ggplot2, 覆盖构建简单图表并进行修饰的基础知识 Part 2: Customiz ...

  2. [DP]换钱的最小货币数

    题目一 给定数组arr,数组中有N个元素,其中所有的之都为整数且不重复.每个只代表一种面值的货币,每种面值的货币可以使用任意张,在给定一个整数aim代表要找的钱数,求组成aim的最少货币数. 解法 依 ...

  3. 【Mac】快速复制文件路径

    一.使用Automator新建服务 二.配置 三.使用 四.创建快捷键 一.使用Automator新建服务 在应用程序文件夹里打开Automator,选择文件菜单,新建一个服务,如下  二.配置 在 ...

  4. mysql之innodb存储引擎---数据存储结构

    一.背景 1.1文件组织架构 首先看一下mysql数据系统涉及到的文件组织架构,如下图所示: msyql文件组织架构图 从图看出: 1.日志文件:slow.log(慢日志),error.log(错误日 ...

  5. webhook 自动部署代码

    前话: 一般情况,自己在本地开发,代码改动后要push放到线上去看效果,但是我们还要到线上环境手动拉取代码库 git pull 下来, 一来一回太麻烦了. 现在用webhook就可以实现本地开发,pu ...

  6. 虚拟化(二)-VMware workstation

    https://www.cnblogs.com/zhrngM/p/9547945.html vmware workstation的最新版本是10.0.2.相信大家也都使用过,其中的简单的虚拟机的创建, ...

  7. FreeSql (二十七)将已写好的 SQL 语句,与实体类映射进行二次查询

    有时候,我们希望将写好的 sql 语句,甚至是存储过程进行查询,虽然效率不高(有时候并不是效率至上). 巧用AsTable var sql = fsql.Select<UserX>() . ...

  8. linux环境上anaconda的安装与卸载

    首先下载linux上anaconda的安装包: $ wget https://repo.anaconda.com/archive/Anaconda3-5.1.0-Linux-x86_64.sh 然后赋 ...

  9. TestNG(七)组测试

    package com.course.testng.groups; import org.testng.annotations.AfterGroups; import org.testng.annot ...

  10. Failed to access IIS metabase.

    framework4.0 可这样 C:\Inetpub\AdminScripts>cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\ C:\WIN ...