图像 X 轴导数的中值

Median of derivative in X axis of an image

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

  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)))

output: 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。 我在示例中使用的图像是:

I computed derivatives using different methods such as :

  1. convolution with an array [[-1, 1]].
  2. Using the fourier theorem by computing DFT of the image and the array mentioned above, multiplying them and performing IDFT.
  3. Directly through the derivative formula (Computing Fourier, multiplying by index and a constant and computing the inverse).

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

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

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

    您可以将其解释为用线段对数据进行插值,然后对该插值求导:

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

    所以近似假设基础函数是局部线性的。可以通过泰勒展开分析误差,发现误差来自忽略的higher-order项。换句话说,如果函数没有强非线性项,则近似值是准确的。这是 finite differences.

    的一个简单例子
  2. 这与 1 相同,只是使用不同的边界处理来处理图像边缘附近样本的卷积。默认情况下,scipy.signal.convolve2d 执行零填充(尽管您可以使用 boundary 选项来选择其他一些方法)。然而,当通过 DFT 计算卷积时,隐含的边界处理是周期性的,在图像边缘环绕。因此,由于边界处理不同,1 和 2 的结果对于边缘附近的像素边距不同。

  3. 通过在DFT表示下乘以iω来计算导数可以解释为评估sinc interpolation the data. Sinc interpolation assumes the data is band limited的导数。误差来自奈奎斯特频率以外的频谱。特别是,如果从对象边界存在硬跳跃不连续性,则图像不受带宽限制,DFT-based 导数在跳跃附近会有很大误差,表现为振铃伪影。

The main thing that baffles me is that when I try computing the median of this derivative, its ALWAYS 0.0.

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

各种近似导数之间的差异。所以我将在这里关注“为什么总是 0.0?”问题。

导数的中位数仅近似为0.0。当我计算它时,基于有限差分近似(方法#1),我得到 -5.15e-5 作为中位数。接近于零,但不完全为零。

导数在图像的均匀(平坦)区域(例如 out-of-focus 背景)中为 0。图像中的其他特征往往既有正边也有负边,使得导数图像的直方图非常对称:

这种对称性导致此类图像的中值(以及平均值)接近于零。然而,这并非总是如此。例如,如果图像的左边缘比右边缘更亮(或相反),则图像上一定存在净梯度,导致均值或中值不为零。