我想将Otsu阈值应用于图像渐变(以消除噪点)。之后,我想计算渐变方向。不幸的是,当我这样做时,我只能得到0到90度之间的渐变方向。如果没有Otsu阈值,则该值在0到360之间。

在Python中查看我的代码

import numpy as np
import cv2

img = cv2.imread('Ob.png',cv2.IMREAD_GRAYSCALE)
img = img.astype('float32')
img2 =
dst1 = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
dst2 = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)

ret1,th1 = cv2.threshold(dst1.astype(np.uint8),0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
ret2,th2 = cv2.threshold(dst2.astype(np.uint8),0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

mag, ang = cv2.cartToPolar(dst1.astype(np.float32),dst2.astype(np.float32))
np.rad2deg(ang)

最佳答案

您的代码中发生的事情很容易解释:

这两个Sobel滤波器的输出dst1dst2是梯度 vector 的x和y分量。对于一个给定的像素,梯度 vector 由(dst1[i,j]dst2[i,j])给出。该 vector 可以具有任何值,例如(5.8,-2.1),导致大约340度的 Angular 。

接下来,为这两个图像设置阈值。 Otsu阈值化将找到一个值,该值可将图像很好地分为低强度像素和高强度像素。这些分别被分配了0和255的值。但是首先,您将浮点图像转换为uint8,并将所有负值都设置为0。因此,我们的 vector (5.8,-2.1)首先转换为(5,0),然后进行阈值处理,之后它变为( 255,0)或(0,0),取决于5落在阈值的哪一边。

因此,我们已将340度角的 vector 转换为0度角或无可计算 Angular vector (尽管atan2(0,0)通常也产生0)。

实际上,所有 vector 都变为(0,0),(0,255),(255,0)或(255,255),这意味着您只能找到0、45和90度的 Angular 。

相反,您应该做的是计算幅度和阈值(我不知道Otsu是否是此类图像的理想方法)。接下来,仅将幅度大于阈值的那些像素使用 Angular 。

另一个常见的替代方法是使用高斯梯度而不是Sobel。在那里,您可以设置一个平滑(正则化)参数,该参数可以消除或多或少的噪声。我经常看到这是在高斯模糊之后加上Sobel滤波器实现的,尽管对我来说直接使用高斯导数滤波器更有意义。

关于python - 大津阈值和图像渐变方向,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52572051/

10-15 06:59