Sobel梯度幅值的高效计算

2 投票
1 回答
4334 浏览
提问于 2025-04-16 20:50

我现在用这段代码来计算Sobel梯度的大小:

sobel_x = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_16S, 1)
sobel_y = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_16S, 1)
cv.Sobel(im, sobel_x, 1, 0, 3)
cv.Sobel(im, sobel_y, 0, 1, 3)

width, height = cv.GetSize(im)
for i in range(width*height):
    x, _, _, _ = cv.Get1D(sobel_x, i)
    y, _, _, _ = cv.Get1D(sobel_y, i)
    px = int(math.sqrt(x*x + y*y))
    cv.Set1D(sobel, i, px)

这个方法挺简单的,但效率不高,因为我一个一个像素地访问。我希望能在OpenCV中找到更好的方法:

sobel_x2 = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_32S, 1)
sobel_y2 = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_32S, 1)
sobel_2  = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_32S, 1)
cv.Mul(sobel_x, sobel_x, sobel_x2)
cv.Mul(sobel_y, sobel_y, sobel_y2)
cv.Add(sobel_x2, sobel_y2, sobel_2)

在这里,我只是把图像平方后再相加。这样虽然会占用更多内存,但应该会更快,因为现在有些操作可以同时进行。我遇到的问题是没有逐元素的平方根函数(cv.Sqrt似乎只适用于标量)。

有没有什么好主意?

1 个回答

3

正如你已经注意到的,cv.Sqrt() 在Python中只能接受一个标量值。因为有一个等效的函数,cv::sqrt(),它可以对每个元素进行平方根运算,所以这个函数应该也会在大部分自动生成的Python绑定中出现。也许你用的OpenCV版本有点问题。

不管怎样,你可以使用 cv.Pow() 来得到相同的结果:

cv.Pow(src, dst, 0.5)

虽然这可能没有 cv.Sqrt() 快,但仍然会比逐个计算要快很多。

撰写回答