如何在OpenCV中使用1D梯度计算具有不同矢量范数的2D Sobel?

r6hnlfcb  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(106)

OpenCV使用此处定义的Sobel算子的实现(details here)。在该实现中,生成水平导数,然后生成垂直导数,然后将梯度计算为导数的L2范数。
假设我想使用L1范数来代替,为了证明这一点,我拍摄了一张图像,并尝试从OpenCV的Sobel()中获得与手动计算梯度的L2范数相同的结果:

import cv2

z_img = cv2.imread(".\\some_image.tif", cv2.IMREAD_UNCHANGED)

z_px_rows = z_img.shape[0]
z_px_cols = z_img.shape[1]

print(f'Center pixel intensity (original): {z_img[z_px_rows // 2, z_px_cols // 2]}')

gx = cv2.Sobel(z_img, cv2.CV_32F, 1, 0, ksize=13)
print(f'Center pixel intensity (gx): {gx[z_px_rows // 2, z_px_cols // 2]}')

gy = cv2.Sobel(z_img, cv2.CV_32F, 0, 1, ksize=13)
print(f'Center pixel intensity (gy): {gy[z_px_rows // 2, z_px_cols // 2]}')

mag, _ = cv2.cartToPolar(gx, gy)
print(f'Center pixel intensity (homebrew sobel): {mag[z_px_rows // 2, z_px_cols // 2]}')

native_sobel = cv2.Sobel(z_img, cv2.CV_32F, 1, 1, ksize=13)
print(f'Center pixel intensity (native sobel): {native_sobel[z_px_rows // 2, z_px_cols // 2]}')

这里我使用了一个32位浮点图像,其中最小值为0.0,最大值约为600.0。

Center pixel intensity (original): 537.156982421875
Center pixel intensity (gx): -220087.90625
Center pixel intensity (gy): 350005.25
Center pixel intensity (homebrew sobel): 413451.78125
Center pixel intensity (native sobel): 16357.7548828125

显然,有些地方不太对劲。我希望最后两个值是相同的(不是***完全***相同,但肯定很接近)。我试着将图像中的像素归一化到范围[0,1],但没有帮助。我试着将图像转换为8位无符号,但也没有帮助。我对解释这种差异的实现有什么误解?

ryevplcw

ryevplcw1#

你在拿“苹果”和“桔子”作比较。
在Python/OpenCV中,cv2.Sobel()计算X方向导数、Y方向导数或混合导数,如下所示:

这与梯度的大小不同:

其中x(I) = X来自索贝尔的方向导数,y(I) = Y来自索贝尔的方向导数,其中I = src,幅值= dst
如果需要L1范数,则使用代替上面的平方根幅度

magnitude(I) = |x(I)| + |y(I)|

其中,x(I) = X方向导数和y(I) = Y方向导数(来自Sobel),I = src,幅值=点

相关问题