【问题标题】:Why does cv2.bilateralFilter behave so differently for different data types?为什么 cv2.bilateralFilter 对于不同的数据类型表现如此不同?
【发布时间】:2021-07-05 10:50:33
【问题描述】:

正如标题所述,cv2.bilateralFilter 为何对不同的 dtype 表现如此不同? cv2.bilateralFilter 仅适用于 np.float32np.uint8 dtypes,文档说。但是当我将它应用于我的图像时,两种 dtype 的输出看起来大不相同。

我正在使用 skimage 函数 img_as_x 在数据类型之间进行转换,因为我听说在处理图像时必须从不使用 .astype(x)。所以我的代码如下所示:

Radargram = img_as_float32(cv2.imread(image)[:,:,::-1])
CropRadGram = (Radargram[700:2450,:,:])[:,:,0]
SigmaAll = 10
RadGramFilter = cv2.bilateralFilter(img_as_ubyte(CropRadGram), -1, SigmaAll, SigmaAll) #As uint8
RadGramFilter2 = cv2.bilateralFilter(CropRadGram, -1, SigmaAll, SigmaAll) #as float32
plt.figure(figsize=(20,20)); plt.imshow(RadGramFilter,cmap='gray')
plt.figure(figsize=(20,20)); plt.imshow(RadGramFilter2,cmap='gray')
RadGramFilterImg = Image.fromarray(img_as_ubyte(RadGramFilter)) #Transform to uint8 and construct image
RadGramFilterImg.save(f'Prepared_CropGrams/{IMG_nr}_RAD_prepared.png') #Save the image

RadGramFilterRadGramFilter2 的输出可以在这里看到:

谢谢

【问题讨论】:

    标签: python image opencv scikit-image


    【解决方案1】:

    [...] 我听说在处理图像时必须从不使用.astype(x)

    这在很大程度上取决于使用的库和用例!在这个非常具体的示例中,首先使用 img_as_float32 而不是 .astype(np.float32) 会导致观察到的行为!

    查看cv2.bilateralFilter 上的文档,我们看到有一个参数sigmaColor,您将其设置为20,用于np.uint8np.float32 图像。但是,sigmaColor = 20 仅适用于此处的np.uint8 情况,因为它的值在[0 ... 255] 的范围内。另一方面,您的np.float32 图像的值在[0.0 ... 1.0] 范围内,这解释了严重的模糊。

    因此,有两个选项可以解决这个问题,都涉及手动缩放:

    1. 在开头使用.astype(np.float32)。然后,您可以使用sigmaColor = 20,但生成的图像将具有0.0 ... 255.0 范围内的值,因此您需要除以255,例如在使用 matplotlib 进行绘图之前。
    import cv2
    import matplotlib.pyplot as plt
    import numpy as np
    from skimage import img_as_float32, img_as_ubyte
    
    # Use .astype(x) instead of img_as_x
    img = cv2.imread('path/to/your/image.jpg')[..., ::-1]
    filter_uint8 = cv2.bilateralFilter(img, 200, 200, 200)
    filter_float32 = cv2.bilateralFilter(img.astype(np.float32), 200, 200, 200)
    
    plt.figure(1, figsize=(14, 8))
    plt.subplot(2, 2, 1), plt.imshow(img), plt.title('Original image')
    plt.subplot(2, 2, 2), plt.imshow(filter_uint8), plt.title('uint8 filtered')
    plt.subplot(2, 2, 3), plt.imshow(filter_float32), plt.title('float32 filtered')
    plt.subplot(2, 2, 4), plt.imshow(filter_float32 / 255), plt.title('float32 filtered, corrected')
    plt.tight_layout()
    

    1. cv2.bilateralFilter 调用中将sigmaColor 除以255。因此,您的结果将直接具有0.0 ... 1.0 范围内的值:
    import cv2
    import matplotlib.pyplot as plt
    from skimage import img_as_float32, img_as_ubyte
    
    # Scale sigmaColor w.r.t. to float value range of [0.0 ... 1.0]
    img = img_as_float32(cv2.imread('path/to/your/image.jpg')[..., ::-1])
    filter_uint8 = cv2.bilateralFilter(img_as_ubyte(img), 200, 200, 200)
    filter_float32 = cv2.bilateralFilter(img, 200, 200, 200)
    filter_float32_corr = cv2.bilateralFilter(img, 200, 200/255, 200)
    
    plt.figure(0, figsize=(14, 8))
    plt.subplot(2, 2, 1), plt.imshow(img), plt.title('Original image')
    plt.subplot(2, 2, 2), plt.imshow(filter_uint8), plt.title('uint8 filtered')
    plt.subplot(2, 2, 3), plt.imshow(filter_float32), plt.title('float32 filtered')
    plt.subplot(2, 2, 4), plt.imshow(filter_float32_corr), plt.title('float32 filtered, corrected')
    plt.tight_layout(), plt.show()
    

    ----------------------------------------
    System information
    ----------------------------------------
    Platform:      Windows-10-10.0.16299-SP0
    Python:        3.9.1
    Matplotlib:    3.4.0
    NumPy:         1.20.2
    OpenCV:        4.5.1
    scikit-image:  0.18.1
    ----------------------------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-04
      • 2012-09-13
      • 2013-10-13
      • 2013-09-13
      • 2013-02-23
      • 2018-12-18
      • 1970-01-01
      相关资源
      最近更新 更多