python 如何在 Canny 边缘检测器中量化方向
How to quantize directions in Canny edge detector in python
我试图理解 python 中 Canny 运算符的实现
我在 Rosettacode.org 上找到了,但不明白它是如何计算 thetaQ 的。为什么它在这个公式中使用 5 以及它如何量化方向?
有人可以帮我吗?
#!/bin/python
import numpy as np
from scipy.ndimage.filters import convolve, gaussian_filter
from scipy.misc import imread, imshow
def CannyEdgeDetector(im, blur = 1, highThreshold = 91, lowThreshold = 31):
im = np.array(im, dtype=float) #Convert to float to prevent clipping values
#Gaussian blur to reduce noise
im2 = gaussian_filter(im, blur)
#Use sobel filters to get horizontal and vertical gradients
im3h = convolve(im2,[[-1,0,1],[-2,0,2],[-1,0,1]])
im3v = convolve(im2,[[1,2,1],[0,0,0],[-1,-2,-1]])
#Get gradient and direction
grad = np.power(np.power(im3h, 2.0) + np.power(im3v, 2.0), 0.5)
theta = np.arctan2(im3v, im3h)
thetaQ = (np.round(theta * (5.0 / np.pi)) + 5) % 5 #Quantize direction
#Non-maximum suppression
gradSup = grad.copy()
for r in range(im.shape[0]):
for c in range(im.shape[1]):
#Suppress pixels at the image edge
if r == 0 or r == im.shape[0]-1 or c == 0 or c == im.shape[1] - 1:
gradSup[r, c] = 0
continue
tq = thetaQ[r, c] % 4
if tq == 0: #0 is E-W (horizontal)
if grad[r, c] <= grad[r, c-1] or grad[r, c] <= grad[r, c+1]:
gradSup[r, c] = 0
if tq == 1: #1 is NE-SW
if grad[r, c] <= grad[r-1, c+1] or grad[r, c] <= grad[r+1, c-1]:
gradSup[r, c] = 0
if tq == 2: #2 is N-S (vertical)
if grad[r, c] <= grad[r-1, c] or grad[r, c] <= grad[r+1, c]:
gradSup[r, c] = 0
if tq == 3: #3 is NW-SE
if grad[r, c] <= grad[r-1, c-1] or grad[r, c] <= grad[r+1, c+1]:
gradSup[r, c] = 0
.........
atan2
returns [-π,π] 范围内的值。公式 (np.round(theta * (5.0 / np.pi)) + 5)
将其转换为具有四舍五入值的范围 [0,10]。然后,他们取值模 5,得到范围 [0,4] 内的整数,将 5 和 10 映射到 0、6 到 1,等等。也就是说,0、-π 和 π 都映射到同一个整数.
后来他们取该值模 4,将 4 映射到 0。那是我不明白的部分。这对我来说似乎是错误的。这是映射:
您可以看到,刚好高于 π/2 的值被映射为 3,刚好低于 π/2 的值被映射为 2。此外,映射到 0 的角度范围是映射到其他角度的范围的两倍。我会以不同的方式四舍五入这些角度。
无论如何,Canny 过滤器的典型实现不会量化角度,而是使用插值来读取像素之间的值。
此外,使用 Sobel 滤波器计算导数很奇怪,尤其是因为它们是在高斯滤波器之后应用的。这里应该改用高斯滤波器的导数,一步平滑计算导数。
我试图理解 python 中 Canny 运算符的实现 我在 Rosettacode.org 上找到了,但不明白它是如何计算 thetaQ 的。为什么它在这个公式中使用 5 以及它如何量化方向? 有人可以帮我吗?
#!/bin/python
import numpy as np
from scipy.ndimage.filters import convolve, gaussian_filter
from scipy.misc import imread, imshow
def CannyEdgeDetector(im, blur = 1, highThreshold = 91, lowThreshold = 31):
im = np.array(im, dtype=float) #Convert to float to prevent clipping values
#Gaussian blur to reduce noise
im2 = gaussian_filter(im, blur)
#Use sobel filters to get horizontal and vertical gradients
im3h = convolve(im2,[[-1,0,1],[-2,0,2],[-1,0,1]])
im3v = convolve(im2,[[1,2,1],[0,0,0],[-1,-2,-1]])
#Get gradient and direction
grad = np.power(np.power(im3h, 2.0) + np.power(im3v, 2.0), 0.5)
theta = np.arctan2(im3v, im3h)
thetaQ = (np.round(theta * (5.0 / np.pi)) + 5) % 5 #Quantize direction
#Non-maximum suppression
gradSup = grad.copy()
for r in range(im.shape[0]):
for c in range(im.shape[1]):
#Suppress pixels at the image edge
if r == 0 or r == im.shape[0]-1 or c == 0 or c == im.shape[1] - 1:
gradSup[r, c] = 0
continue
tq = thetaQ[r, c] % 4
if tq == 0: #0 is E-W (horizontal)
if grad[r, c] <= grad[r, c-1] or grad[r, c] <= grad[r, c+1]:
gradSup[r, c] = 0
if tq == 1: #1 is NE-SW
if grad[r, c] <= grad[r-1, c+1] or grad[r, c] <= grad[r+1, c-1]:
gradSup[r, c] = 0
if tq == 2: #2 is N-S (vertical)
if grad[r, c] <= grad[r-1, c] or grad[r, c] <= grad[r+1, c]:
gradSup[r, c] = 0
if tq == 3: #3 is NW-SE
if grad[r, c] <= grad[r-1, c-1] or grad[r, c] <= grad[r+1, c+1]:
gradSup[r, c] = 0
.........
atan2
returns [-π,π] 范围内的值。公式 (np.round(theta * (5.0 / np.pi)) + 5)
将其转换为具有四舍五入值的范围 [0,10]。然后,他们取值模 5,得到范围 [0,4] 内的整数,将 5 和 10 映射到 0、6 到 1,等等。也就是说,0、-π 和 π 都映射到同一个整数.
后来他们取该值模 4,将 4 映射到 0。那是我不明白的部分。这对我来说似乎是错误的。这是映射:
您可以看到,刚好高于 π/2 的值被映射为 3,刚好低于 π/2 的值被映射为 2。此外,映射到 0 的角度范围是映射到其他角度的范围的两倍。我会以不同的方式四舍五入这些角度。
无论如何,Canny 过滤器的典型实现不会量化角度,而是使用插值来读取像素之间的值。
此外,使用 Sobel 滤波器计算导数很奇怪,尤其是因为它们是在高斯滤波器之后应用的。这里应该改用高斯滤波器的导数,一步平滑计算导数。