从 cv2 解释 Sobel
Interpreting Sobel from cv2
我试图从 Python 中的 cv2
理解 Sobel 卷积。
根据 documentation Sobel 内核是
-1 0 1
-2 0 2
-1 0 1
因此,我尝试将其应用于以下 img
(二进制 3x3
数组):
0 1 0
1 0 1
0 1 0
现在,我在解释输出时遇到了问题。我手工计算得到了不同的结果。据我所知,我必须将内核居中于每个像素 (i,j)
并乘以元素并求和。
因此,输出 中的第一个条目应该是 2
。程序 returns 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]]
阅读您的 documentation 页面的第二段:
Another common feature of the functions and classes described in this section is that, unlike simple arithmetic functions, they need to extrapolate values of some non-existing pixels. For example, if you want to smooth an image using a Gaussian 3x3 filter, then, when processing the left-most pixels in each row, you need pixels to the left of them, that is, outside of the image. You can let these pixels be the same as the left-most image pixels (“replicated border” extrapolation method), or assume that all the non-existing pixels are zeros (“constant border” extrapolation method), and so on. OpenCV enables you to specify the extrapolation method. For details, see the function borderInterpolate()
and discussion of the borderType
parameter in the section and various functions below.
让它按预期工作
要使其按您预期的那样工作,您必须明确指定要用零值插入边框。像这样:
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_101
而 BORDER_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 像素后的正确值全为零 – 这就是您通过 运行ning 脚本得到的值。
我试图从 Python 中的 cv2
理解 Sobel 卷积。
根据 documentation Sobel 内核是
-1 0 1
-2 0 2
-1 0 1
因此,我尝试将其应用于以下 img
(二进制 3x3
数组):
0 1 0
1 0 1
0 1 0
现在,我在解释输出时遇到了问题。我手工计算得到了不同的结果。据我所知,我必须将内核居中于每个像素 (i,j)
并乘以元素并求和。
因此,输出 中的第一个条目应该是 2
。程序 returns 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]]
阅读您的 documentation 页面的第二段:
Another common feature of the functions and classes described in this section is that, unlike simple arithmetic functions, they need to extrapolate values of some non-existing pixels. For example, if you want to smooth an image using a Gaussian 3x3 filter, then, when processing the left-most pixels in each row, you need pixels to the left of them, that is, outside of the image. You can let these pixels be the same as the left-most image pixels (“replicated border” extrapolation method), or assume that all the non-existing pixels are zeros (“constant border” extrapolation method), and so on. OpenCV enables you to specify the extrapolation method. For details, see the function
borderInterpolate()
and discussion of theborderType
parameter in the section and various functions below.
让它按预期工作
要使其按您预期的那样工作,您必须明确指定要用零值插入边框。像这样:
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_101
而 BORDER_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 像素后的正确值全为零 – 这就是您通过 运行ning 脚本得到的值。