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位无符号,但也没有帮助。我对解释这种差异的实现有什么误解?
1条答案
按热度按时间ryevplcw1#
你在拿“苹果”和“桔子”作比较。
在Python/OpenCV中,cv2.Sobel()计算X方向导数、Y方向导数或混合导数,如下所示:
这与梯度的大小不同:
其中
x(I) = X
来自索贝尔的方向导数,y(I) = Y
来自索贝尔的方向导数,其中I
= src,幅值= dst如果需要L1范数,则使用代替上面的平方根幅度
其中,
x(I) = X
方向导数和y(I) = Y
方向导数(来自Sobel),I
= src,幅值=点