Sobel过滤器效果不佳

问题描述

我试图在python中实现sobel过滤器,但输出效果不佳且充满噪音。 我得到的输出图像是:

enter image description here

我给的输入是(模糊之后):

enter image description here

sobel过滤器的代码如下:

def sobel_filters(img):
  Kx = np.array([[-1,1],[-2,2],[-1,1]])
  Ky = np.array([[1,2,[0,0],-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。 我期望输出类似于此处显示内容https://www.adeveloperdiary.com/data-science/computer-vision/how-to-implement-sobel-edge-detection-using-python-from-scratch/

解决方法

这是在Python / OpenCV中执行此操作的一种方法。您的问题是您的导数未正确归一化,应作为浮点数进行处理。您的规范化也没有考虑负值。在这个答案中,我利用了OpenCV内置的Sobel和其他方法。因此无需引入scipy.ndimage

输入:

enter image description here

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,ksize=3)
sobely = cv2.Sobel(blur,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,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,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()

Sobel X(规范化):

enter image description here

Sobel Y(标准化):

enter image description here

苏贝尔幅值:

enter image description here

,

这是在Python / OpenCV中使用浮动图像和适当规范化的方法。没有浮点数据,您将只获得单方面的导数(而不是正面和负面的结果)。

正如Cris Luengo所指出的,相对于OpenCV中的标准衍生词,您答案中的衍生词是错误的。参考文献中的导数用于正确的卷积。但是Scipy具有卷积和相关性。实际上,大多数“卷积”实际上都是相关性。 (OpenCV cv2.filter2D就是这样。该函数实际上是计算相关性,而不是卷积)。因此,我已将内核的相关性更正为与OpenCV Sobel中或cv2.filter2D()使用的相关性一致。卷积和相关性由转置关联。参见https://medium.com/@aybukeyalcinerr/correlation-vs-convolution-filtering-2711d8bb3666

输入:

enter image description here

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,1.3)

# define Sobel X and Y (correlation) kernels
Kx = np.array([[-1,1],[-2,2],[-1,1]])

Ky = np.array([[-1,-2,-1],[ 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,Ky)

# optionally normalize to range 0 to 255 for proper display and saving as 8-bit data.
sobelx_norm= exposure.rescale_intensity(sobelx,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,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)  
cv2.waitKey(0)
cv2.destroyAllWindows()

Sobel X(规范化):

enter image description here

Sobel Y(标准化):

enter image description here

苏贝尔幅值:

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...