我试图理解cv2在Python中的Sobel卷积。
根据文档的说法,Sobel内核是
-1 0 1
-2 0 2
-1 0 1因此,我尝试将其应用于以下img (二进制3x3数组):
0 1 0
1 0 1
0 1 0现在,我有一个问题来解释输出。我手工计算得到了不同的结果。正如我所知道的那样,我必须在每个像素的(i,j)上对内核进行中心化,并对元素进行分组和求和。
因此,输出的第一个条目应该是2。程序返回0。
我说错了吗?要是那样就好了。
码
import cv2
import numpy as np
img = np.array([[0,1,0],[1,0,1],[0,1,0]]).astype(float)
# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=3)
# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
print 'img'
print img
print 'sobelx8u'
print sobelx8u
print 'sobelx64f'
print sobelx64f
print 'abs_sobel64f'
print abs_sobel64f
print 'sobel_8u'
print sobel_8u输出
img
[[ 0. 1. 0.]
[ 1. 0. 1.]
[ 0. 1. 0.]]
sobelx8u
[[0 0 0]
[0 0 0]
[0 0 0]]
sobelx64f
[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]
abs_sobel64f
[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]
sobel_8u
[[0 0 0]
[0 0 0]
[0 0 0]]发布于 2018-07-06 13:59:34
阅读文档页面的第二段:
本节中描述的函数和类的另一个共同特征是,与简单的算术函数不同,它们需要外推一些不存在像素的值。例如,如果您想使用高斯3x3滤波器平滑图像,那么当处理每行中最左边的像素时,您需要它们左边的像素,即图像之外的像素。您可以让这些像素与最左边的图像像素相同(“复制边界”外推方法),或者假设所有不存在的像素都是零(“常量边界”外推方法)等等。OpenCV使您能够指定外推方法。有关详细信息,请参阅函数
borderInterpolate(),并在本节中讨论borderType参数和下面的各种函数。
让它像你期望的那样工作
要使它按照您的预期工作,您必须显式指定要用零值插入边框。如下所示:
import cv2
import numpy as np
img = np.array([[0,1,0],[1,0,1],[0,1,0]]).astype(float)
border = cv2.borderInterpolate(0, 1, cv2.BORDER_CONSTANT)
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3, borderType=border)
print 'img'
print img
print 'sobelx64f'
print sobelx64f输出:
img
[[ 0. 1. 0.]
[ 1. 0. 1.]
[ 0. 1. 0.]]
sobelx64f
[[ 2. 0. -2.]
[ 2. 0. -2.]
[ 2. 0. -2.]]默认边框类型
borderType的默认值是BORDER_DEFAULT,它在我的机器上与BORDER_REFLECT_101相同。您可以运行此脚本在计算机上确认它:
import cv2
for var in dir(cv2):
if not var.startswith('BORDER_'): continue
if cv2.__dict__[var] == cv2.BORDER_DEFAULT:
print 'BORDER_DEFAULT ==', var输出:
BORDER_DEFAULT == BORDER_DEFAULT
BORDER_DEFAULT == BORDER_REFLECT101
BORDER_DEFAULT == BORDER_REFLECT_101BORDER_REFLECT_101的工作方式与您的结果完全一致。以下是对不同边界类型的解释:
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'解释你得到了什么
因此,默认的边框内插类型(即BORDER_REFLECT_101)使数组在计算之前看起来如下:
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0通过简单的算法,您可以确认将Sobel内核应用到内部3x3像素后的正确值都是零--这就是通过运行脚本得到的结果。
https://stackoverflow.com/questions/51179926
复制相似问题