首页 > 解决方案 > 图像 X 轴导数的中位数

问题描述

我使用不同的方法计算导数,例如:

  1. 与数组 [[-1, 1]] 进行卷积。
  2. 通过计算图像和上述数组的 DFT 来使用傅立叶定理,将它们相乘并执行 IDFT。
  3. 直接通过导数公式(计算傅立叶,乘以指数和常数并计算逆)。

所有方法的工作原理几乎相同,但略有不同。

我们将不胜感激解释为什么他们最终会得到略有不同的结果。

在计算了这些之后,我开始使用结果来了解它,我发现了一些让我感到困惑的东西:

主要让我感到困惑的是,当我尝试计算这个导数的中位数时,它总是 0.0。

这是为什么?

我添加了用于计算它的代码(至少是第一种方法),因为也许我做错了什么。

from scipy.signal import convolve2d

im = sl.read_image(r'C:\Users\ahhal\Desktop\Essentials\Uni\year3\SemesterA\ImageProcessing\Exercises\Ex2\external\monkey.jpg', 1)


b = [[-1, 1]]

print(np.median(convolve2d(im, b)))

输出:0.0

read_image功能是我自己的,这是实现:

from imageio import imread
from skimage.color import rgb2gray
import numpy as np
def read_image(filename, representation):
    """
    Receives an image file and converts it into one of two given representations.
    :param filename: The file name of an image on disk (could be grayscale or RGB).
    :param representation: representation code, either 1 or 2 defining wether the output
    should be a grayscale image (1) or an RGB image (2). If the input image is grayscale,
    we won't call it with representation = 2.
    :return: An image, represented by a matrix of type (np.float64) with intensities
    normalized to the range [0,1].
    """
    assert representation in [1, 2]

    # reads the image
    im = imread(filename)
    if representation == 1:  # If the user specified they need grayscale image,
        if len(im.shape) == 3:  # AND the image is not grayscale yet
            im = rgb2gray(im)  # convert to grayscale (**Assuming its RGB and not a different format**)

    im_float = im.astype(np.float64)  # Convert the image type to one we can work with.

    if im_float.max() > 1:  # If image values are out of bound, normalize them.
        im_float = im_float / 255

    return im_float

编辑 2: 我在几个不同的图像上进行了尝试,并且都得到了 0.0。我在示例中使用的图像是: 在此处输入图像描述

标签: pythonimage-processingconvolutionmedianderivative

解决方案


我使用不同的方法计算导数,例如:

  1. 与数组 [[-1, 1]] 进行卷积。
  2. 通过计算图像和上述数组的 DFT 来使用傅立叶定理,将它们相乘并执行 IDFT。
  3. 直接通过导数公式(计算傅立叶,乘以指数和常数并计算逆)。

这些导数方法都是近似的,并做出不同的假设:

  1. [[-1, 1]] 的卷积计算相邻元素之间的差异,

    derivative ~= data[n+1] − data[n]
    

    您可以将其解释为用线段插值数据,然后取该插值的导数:

    I(x) = data[n] + (data[n+1] − data[n]) * (x − n)
    

    所以近似假设基础函数是局部线性的。您可以通过泰勒展开分析误差,发现误差来自忽略的高阶项。换句话说,如果函数没有强非线性项,则近似值是准确的。这是一个简单的有限差分情况。

  2. This is the same as 1, except with different boundary handling to handle convolution of samples near the edges of the image. By default, scipy.signal.convolve2d does zero padding (though you can use the boundary option to choose some other methods). However when computing the convolution through the DFT, then implicitly the boundary handling is periodic, wrapping around at the image edges. So the results of 1 and 2 differ for a margin of pixels near the edge because of the different boundary handling.

  3. 通过在 DFT 表示下乘以 iω 来计算导数可以解释为评估sinc 插值数据的导数。Sinc 插值假设数据是带限的。误差来自超过奈奎斯特频率的频谱。特别是,如果从对象边界存在硬跳跃不连续性,则图像不受频带限制,并且基于 DFT 的导数在跳跃附近将有很大的误差,表现为振铃伪影。

主要让我感到困惑的是,当我尝试计算这个导数的中位数时,它总是 0.0。

我不知道为什么会发生这种情况,但不应该总是如此。例如,如果每个图像行是单位 ramp data[n] = n,则 [[-1, 1]] 的卷积在任何地方都等于 1,除非取决于可能不在边缘的边界处理,因此中位数为 1。


推荐阅读