Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响

锚点anchor位置及borderValue的改变对膨胀腐蚀的影响

腐蚀:卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是 1,那么中心元素就保持原来的像素值,否则就变为零。
膨胀:与卷积核对应的原图像的像素值中只要有一个是 1,中心元素的像素值就是 1。

这个描述看起来有点生硬,为了进一步理解opencv对腐蚀与膨胀都是针对灰度图的形态学操作,还是自己操作一遍。
先看下 Python wrapper for OpenCV里的定义
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第1张图片

1. 腐蚀膨胀自定义kernel 默认anchor=(-1,-1)

anchor – 卷积核锚点。其默认值为(-1,-1)说明位于kernel的中心位置
==>查看源码opencv-4.1.1\modules\imgproc\src\filterengine.hpp
static inline Point normalizeAnchor( Point anchor, Size ksize )
{
	if( anchor.x == -1 )
	    anchor.x = ksize.width/2;
	if( anchor.y == -1 )
	    anchor.y = ksize.height/2;
	CV_Assert( anchor.inside(Rect(0, 0, ksize.width, ksize.height)) );
	return anchor;
}

首先定义一个5*5的图片矩阵表示,修改其中几个像素为1

img_5X5= np.zeros((5,5), dtype=np.uint8)
img_5X5[2,2]=1
img_5X5[3,3]=1
img_5X5[3,4]=1

它每个像素对应的值打印下如下:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第2张图片

再义一个3 * 3的结构元素kernel,该结构元素用3*3的矩阵表示

  1. 其中为1的单元,表示该单元在结构元素中有效(不参与结果运算)
kernel = np.zeros((3,3),np.uint8)
kernel[1,1]=1;
kernel[0,0]=1;
  1. 定义一个锚点,默认锚点为(-1,-1)表示在正中心,在单元格中用红色字体表示。黄色填充色为有效单元.
    在这里插入图片描述
    腐蚀或膨胀的操作:用结构元素(kernel)的锚点位置对齐图像的像素点,然后逐个从左到右至上而下的滑动到每个像素。结构元素中为1的各个坐标格子会与相应的像素对齐。
    Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第3张图片
    腐蚀操作就是取其中的最小值,代替原素像素值
    膨胀操作则就是取其中的最大值,用最大值代替原像素,

腐蚀操作
-举个有操作影响的例子当kernel移动到img_5X5(2,2)即图中心点位置,腐蚀操作:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第4张图片
腐蚀img_5X5(2,2)应该等是 min(0,1)最小值0
同理移动到img_5X5(3,4)腐蚀结果也是0
但是到img_5X5(3,3),min(1,1)=1
整体img_5X5的腐蚀结果为:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第5张图片
这里可以看出,其实3*3的kernel在默认锚点为(-1,-1)只有时候只有黄色填充部分有效:

在这里插入图片描述
膨胀操作
kernel在默认锚点为(-1,-1)膨胀操作结果:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第6张图片

2. 自定义kernel 观察锚点anchor=(0,0)或anchor=(2,2)的改变对腐蚀膨胀结果的影响

2.2 改变kernel锚点为anchor=(0,0)的腐蚀膨胀操作

锚点改变为坐标anchor=(0,0),即红色字体1为锚点,黄色填充部分为有效单元:
在这里插入图片描述
当kernel移动到img_5X5(2,2)即图中心点位置,腐蚀操作:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第7张图片

  • 腐蚀img_5X5(2,2)应该等是 min(1,1)=1
  • 腐蚀img_5X5(3,3),min(1,0)=0
  • 腐蚀img_5X5(3,4)腐蚀结果min(1)=1

腐蚀img_5X5(3,4)腐蚀结果min(1)=1 理解为当腐蚀时在opencv中kernel为1的单元格和图像img_5X5没有交叉的有效单元,锚点参与运算的情况,其值不变。

Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第8张图片

anchor=(0,0)腐蚀的结果:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第9张图片
膨胀的结果:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第10张图片

2.2 改变kernel锚点为anchor=(2,2)腐蚀膨胀操作

cv2.erode(img_5X5,kernel,iterations = 1,anchor=(2,2))
cv2.dilate(img_5X5,kernel,iterations = 1,anchor=(2,2))

此为特殊情况:
在这里插入图片描述
当kernel移动到img_5X5(0,0)位置,opencv中,没有交叉的有效单情况锚点值:当腐蚀时,此时(0,0)位置像素值为255,当膨胀时,(0,0)位置像素值为0

腐蚀:img_5X5(0,0)的值为 min(255)=255
以此类推img_5X5第一行,第一列的腐蚀值都为255
膨胀:img_5X5(0,0)的值为 max(0)=0
以此类推img_5X5第一行,第一列的膨胀值都为0
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第11张图片
img_5X5(4,4)位置的值为min(1,1)=1
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第12张图片
腐蚀结果:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第13张图片
膨胀结果
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第14张图片
总结:完全没有交叉的有效单情况的(且无borderType)锚点值分析 ,锚点分为有没有值的二种情况:
1 锚点有值:原有像素值不变
2 锚点无值:当腐蚀时像素值为255,当膨胀时置像素值为0

2.3 改变kernel锚点为anchor=(2,2),同时修改borderType及borderValue默认选项后的腐蚀膨胀操作

此处设定图像img_5X5外填充值,重新按照kernel锚点anchor=(2,2)的方式腐蚀及膨胀图像
/*
 Various border types, image boundaries are denoted with '|'
 * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
 * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
 * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
 * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
 * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
 */

erosion = cv2.erode(img_5X5,kernel,iterations = 1,anchor=(2,2),borderType=cv2.BORDER_CONSTANT,borderValue=1)
dilate =cv2.dilate(img_5X5,kernel,iterations = 1,anchor=(2,2),borderType=cv2.BORDER_CONSTANT,borderValue=1)

图示绿色部分为img_5X5,蓝色为填充值1:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第15张图片
kernel移动到img_5X5(0,0)位置 锚点为anchor=(2,2)的腐蚀操作值:min(1,1)=1
kernel移动到img_5X5(0,0)位置 锚点为anchor=(2,2)的膨胀操作值:max(1,1)=1
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第16张图片

kernel移动到img_5X5(1,1)位置 锚点为anchor=(2,2)的膨胀操作值:max(1,0)=1
kernel移动到img_5X5(1,1)位置 锚点为anchor=(2,2)的腐蚀操作值:min(1,0)=0
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第17张图片
img_5X5,锚点为anchor=(2,2),borderValue=1时 其腐蚀结果为绿色部分
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第18张图片

img_5X5,锚点为anchor=(2,2),borderValue=1时,第一二行及一二列膨胀值全部为1.其膨胀结果为绿色部分:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第19张图片

其余改变kernel的形态及锚点位置可自行操作研究,原理相同。
不同锚定点对应卷积的起始位置与锚定像素输出示意:
Opencv python 锚点anchor位置及borderValue的改变对膨胀腐蚀的影响_第20张图片

用到的代码:

import cv2
import numpy as np
#自定义5*5矩阵
img_5X5= np.zeros((5,5), dtype=np.uint8)
img_5X5[2,2]=1
img_5X5[3,3]=1
img_5X5[3,4]=1
print(img_5X5)

#卷积核设定生成
kernel = np.zeros((3,3),np.uint8)
kernel[1,1]=1;
kernel[0,0]=1;
print(kernel)

erosion = cv2.erode(img_5X5,kernel,iterations = 1,anchor=(-1,-1))
print(erosion)
dilate =cv2.dilate(img_5X5,kernel,iterations = 1 ,anchor=(-1,-1))
print(dilate)
erosion = cv2.erode(img_5X5,kernel,iterations = 1,anchor=(0,0),borderValue=255)
print(erosion)
dilate =cv2.dilate(img_5X5,kernel,iterations = 1,anchor=(0,0),borderValue=0)
print(dilate)
erosion = cv2.erode(img_5X5,kernel,iterations = 1,anchor=(2,2),borderType=cv2.BORDER_CONSTANT,borderValue=1)
print(erosion)
dilate =cv2.dilate(img_5X5,kernel,iterations = 1,anchor=(2,2),borderType=cv2.BORDER_CONSTANT,borderValue=1)
print(dilate)

cv2.waitKey(0)
cv2.destroyAllWindows()

你可能感兴趣的:(opencv-python)