【发布时间】:2017-08-04 00:06:59
【问题描述】:
我正在尝试在 Python 中实现 sobel 运算符并将其可视化。但是,我正在努力解决如何做到这一点。我有以下代码,当前计算每个像素的梯度。
from PIL import Image
import math
def run():
try:
image = Image.open("brick-wall-color.jpg")
image = image.convert('LA')
apply_sobel_masks(image)
except RuntimeError, e:
print e
def apply_sobel_masks(image):
gx = [
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
]
gy = [
[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]
]
width, height = image.size
for y in range(0, height):
for x in range(0, width):
gradient_y = (
gy[0][0] * get_pixel_safe(image, x - 1, y - 1, 0) +
gy[0][1] * get_pixel_safe(image, x, y - 1, 0) +
gy[0][2] * get_pixel_safe(image, x + 1, y - 1, 0) +
gy[2][0] * get_pixel_safe(image, x - 1, y + 1, 0) +
gy[2][1] * get_pixel_safe(image, x, y + 1, 0) +
gy[2][2] * get_pixel_safe(image, x + 1, y + 1, 0)
)
gradient_x = (
gx[0][0] * get_pixel_safe(image, x - 1, y - 1, 0) +
gx[0][2] * get_pixel_safe(image, x + 1, y - 1, 0) +
gx[1][0] * get_pixel_safe(image, x - 1, y, 0) +
gx[1][2] * get_pixel_safe(image, x + 1, y, 0) +
gx[2][0] * get_pixel_safe(image, x - 1, y - 1, 0) +
gx[2][2] * get_pixel_safe(image, x + 1, y + 1, 0)
)
print "Gradient X: " + str(gradient_x) + " Gradient Y: " + str(gradient_y)
gradient_magnitude = math.sqrt(pow(gradient_x, 2) + pow(gradient_y, 2))
image.putpixel((x, y), #tbd)
image.show()
def get_pixel_safe(image, x, y, layer):
try:
return image.getpixel((x, y))[layer]
except IndexError, e:
return 0
run()
现在 gradient_magnitude 通常是一个远远超出 0-255 范围的值,例如990.0、1002.0、778等
所以我想做的是可视化渐变,但我不确定如何。网上的大部分资源只提到计算梯度的角度和幅度,而没有提到如何在图像中表示。
【问题讨论】:
-
尝试使用梯度幅值图像的最大值和最小值归一化到0-255值,即
displayableGradMagnitude = 255* (gradMagnitude-minGradMagnitude)/(maxGradMagnitude-minGradMagnitude)。 -
谢谢,效果很好。也许将其发布为答案,以便我可以给您您的信用
-
还要注意Solbel卷积核是可分离的。您可以应用带有 [-1,0,1] 的卷积,并在结果上应用带有 [1,2,1] 转置的第二个卷积。这总是更有效,也更容易实施。这两个操作的顺序无关紧要。通过转置两个内核来计算 y 导数。
-
@fbailey:对于每一行,执行
tmp[x]=in[x-1]-in[x+1]。然后,对于每一列,执行out[y]=tmp[y-1]+2*tmp[y]+tmp[y+1]。这给了你 x 导数。抱歉这里的伪代码,这些评论框并没有真正让你做更多的事情。但我相信你可以从那里弄清楚。请注意,您不需要创建临时图像tmp,您可以直接在输出图像中写入两个步骤中的每一个。但是在第二步中,您需要复制您将要处理的列,这样您就不会覆盖您仍然需要的数据。有更聪明的方法可以做到这一点,但这是一个更长的故事。 -
@fbailey:您在每个位置使用 3x3 像素来计算梯度,但是 chris 提到的是您可以将此处理分为第一个 X 方向然后 Y 方向计算(划分 3x3 内核成一个水平向量和一个垂直向量)。阅读 Gonzalez 的 DIP,它包含所有这些信息。附言我会在 12 小时内发布答案。
标签: python image-processing threshold sobel