Python Sobel滤波器的结果很差
我试图用python实现sobel过滤器,但是输出很差,充满了噪声。 我得到的输出图像是: 我给出的输入是(模糊后): sobel过滤器的代码如下:Python Sobel滤波器的结果很差,python,opencv,computer-vision,sobel,Python,Opencv,Computer Vision,Sobel,我试图用python实现sobel过滤器,但是输出很差,充满了噪声。 我得到的输出图像是: 我给出的输入是(模糊后): sobel过滤器的代码如下: def sobel_filters(img): Kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) Ky = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]) Ix = ndimage.filters.convolve(img, Kx)
def sobel_filters(img):
Kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
Ky = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
Ix = ndimage.filters.convolve(img, Kx)
Iy = ndimage.filters.convolve(img, Ky)
G = np.sqrt(np.square(Ix) + np.square(Iy))
G *= 255.0 / G.max()
return G
我用sigma=1.3模糊了结果。输入图像大小为512 x 512。
我希望输出与这里显示的类似:这里有一种在Python/OpenCV中实现这一点的方法。你的问题是你的衍生品没有正确的标准化,应该作为浮动进行处理。您的规范化也不考虑负值。在这个答案中,我使用了OpenCV内置的Sobel和其他方法。因此,没有必要引入scipy.ndimage 输入:
Sobel X(标准化): Sobel Y(标准化): 索贝尔震级:
以下是使用浮点图像和Python/OpenCV中的适当规范化来实现这一点的方法。如果没有浮动数据,则只能得到单边导数(不包括正结果和负结果) 正如Cris Luengo所指出的,您答案中的导数相对于OpenCV中的标准导数是错误的。参考文献中的导数用于适当的卷积。但Scipy同时具有卷积和相关性。事实上,大多数“卷积”都是相关性。(OpenCV cv2.filter2D就是这样。该函数实际上计算相关性,而不是卷积)。因此,我修正了内核,使其与OpenCV Sobel中的内容或cv2.filter2D()使用的内容一致。卷积和相关性通过转置进行关联。看 输入:
Sobel X(标准化): Sobel Y(标准化): 索贝尔震级:
谢谢克里斯。我没有注意到这一问题的迹象。他从他试图复制的链接中得到了这些值。在其中一个例子中,我回答他为什么他的代码不起作用。在另一个例子中,我向他展示了我是如何使用OpenCVCris完成的对不起,当我试图更改规范化时,我重写了错误的答案,然后决定将其放回原处。我不想修理他的索贝尔果仁,因为他是从他列出的参考资料中得到的。但你的观点被很好地理解了,很高兴你指出了这一点。希望他能理解。然而,由于震级考虑了绝对值之和,我认为震级不重要。当然,X和Y导数图像的边缘极性会发生变化。克里斯,我已经编辑了我的答案,以显示正确的内核和图像。并对卷积和相关性给出更好的解释。您发布的链接没有使用正确的Sobel内核。关注维基百科页面,这是正确的:非常感谢!它起作用了!我实际上是在使用我自己的高斯模糊实现,并将结果存储在int8中。转换后,它工作!另外,请注意,您的实现中存在一些错误:在sobely_norm变量中,您使用了相同的参数Ix而不是Iy
import cv2
import numpy as np
import skimage.exposure as exposure
# read the image
img = cv2.imread('gray_lena.png')
# convert to gray
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# blur
blur = cv2.GaussianBlur(gray, (0,0), 1.3, 1.3)
# apply sobel derivatives
sobelx = cv2.Sobel(blur,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(blur,cv2.CV_64F,0,1,ksize=3)
# optionally normalize to range 0 to 255 for proper display
sobelx_norm= exposure.rescale_intensity(sobelx, in_range='image', out_range=(0,255)).clip(0,255).astype(np.uint8)
sobely_norm= exposure.rescale_intensity(sobelx, in_range='image', out_range=(0,255)).clip(0,255).astype(np.uint8)
# square
sobelx2 = cv2.multiply(sobelx,sobelx)
sobely2 = cv2.multiply(sobely,sobely)
# add together and take square root
sobel_magnitude = cv2.sqrt(sobelx2 + sobely2)
# normalize to range 0 to 255 and clip negatives
sobel_magnitude = exposure.rescale_intensity(sobel_magnitude, in_range='image', out_range=(0,255)).clip(0,255).astype(np.uint8)
# save results
cv2.imwrite('gray_lena_sobelx_norm.jpg', sobelx_norm)
cv2.imwrite('gray_lena_sobely_norm.jpg', sobely_norm)
cv2.imwrite('gray_lena_sobel_magnitude.jpg', sobel_magnitude)
# show results
cv2.imshow('sobelx_norm', sobelx_norm)
cv2.imshow('sobely_norm', sobely_norm)
cv2.imshow('sobel_magnitude', sobel_magnitude)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
import scipy.ndimage as ndimage
import skimage.exposure as exposure
# read the image and convert to float
img = cv2.imread('gray_lena.png').astype(np.float32)
# convert to gray
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# blur
blur = cv2.GaussianBlur(gray, (0,0), 1.3, 1.3)
# define Sobel X and Y (correlation) kernels
Kx = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
Ky = np.array([[-1, -2, -1],
[ 0, 0, 0],
[ 1, 2, 1]])
# apply correlations and normalize by sum of absolute values of elements
sobelx = ndimage.filters.correlate(blur, Kx)
sobely = ndimage.filters.correlate(blur, Ky)
#OpenCV alternate:
#sobelx = cv2.filter2D(blur, cv2.CV_32F, Kx)
#sobely = cv2.filter2D(blur, cv2.CV_32F, Ky)
# optionally normalize to range 0 to 255 for proper display and saving as 8-bit data.
sobelx_norm= exposure.rescale_intensity(sobelx, in_range='image', out_range=(0,255)).clip(0,255).astype(np.uint8)
sobely_norm= exposure.rescale_intensity(sobelx, in_range='image', out_range=(0,255)).clip(0,255).astype(np.uint8)
# add and take square root
sobel_magnitude = np.sqrt(np.square(sobelx) + np.square(sobely))
# normalize to range 0 to 255 and clip negatives
sobel_magnitude = exposure.rescale_intensity(sobel_magnitude, in_range='image', out_range=(0,255)).clip(0,255).astype(np.uint8)
# save results
cv2.imwrite('gray_lena_sobelx_norm2.jpg', sobelx_norm)
cv2.imwrite('gray_lena_sobely_norm2.jpg', sobely_norm)
cv2.imwrite('gray_lena_sobel_magnitude2.jpg', sobel_magnitude)
# show results
cv2.imshow('sobelx_norm', sobelx_norm)
cv2.imshow('sobely_norm', sobely_norm)
cv2.imshow('sobel_magnitude', sobel_magnitude)
cv2.waitKey(0)
cv2.destroyAllWindows()