【问题标题】:Having an Issue with understanding bilateral filtering在理解双边过滤时遇到问题
【发布时间】:2021-10-21 11:42:14
【问题描述】:

我再次向您提出有关过滤器的问题,在这种情况下:双边过滤器。我确实了解它的一般概念,并且我确实阅读了有关该主题的几个资料(包括有关 stackoverflow 的一些问题)。大多数来源使用这个等式来描述这个过程(我认为最初是来自this 来源,但在这一点上我不确定):

用这个表示的“一般”高斯滤波器(只考虑空间)

我已经成功实现的高斯滤波器。它仅适用于灰度图像,双边滤波器(希望如此)也是如此。我知道,这绝不是一个好的表现,但它确实起到了作用。一般来说,我认为我只需将乘法与 G(Ip - Iq) 相加即可使其用作双边滤波器。我现在的问题是: (Ip - Iq) 到底代表什么?或者换一种方式问,我在哪里检索这些值?
我不确定是否需要我的代码,但无论如何这是我的实现。我从this stackoverflow discussion 获取的内核算法。

def gaussfiltering (img = [], kernelsize=3, sigma=1.9):
    rows = len(img)
    columns = len(img[0])
    kernel = gaussian_kernel(kernelsize, sigma)
    horizontallyfiltered = iterate_horizontally(kernel, img, rows, columns, len(kernel))
    filtered = iterate_vertically(kernel, horizontallyfiltered, rows, columns, len(kernel))
    return filtered

def gaussian_kernel(kernel_size=3, sigma=1.9):
    x = numpy.linspace(-sigma, sigma, kernel_size+1)
    y = st.norm.cdf(x) 
    kernel = numpy.diff(y)
    return((kernel/kernel.sum()))

def iterate_horizontally (kernel=[], img=[], rows=0, columns=0, kernelsize=0):
    horizontallyfiltered = img.copy()
    for r in range(rows):
        for c in range(columns):
            halved = int(kernelsize/2)
            if ((c - halved) >= 0 and (c + halved) < columns): #is in range for filter
                indexOfImage = c - halved
                summed = 0.0
                for i in range(kernelsize):
                    summed += img[r][indexOfImage] * kernel[i]
                    indexOfImage+=1
                horizontallyfiltered[r][c]=summed
    return horizontallyfiltered

def iterate_vertically (kernel=[], img=[], rows=0, columns=0, kernelsize=0):
    verticallyfiltered = img.copy()
    for r in range(rows):
        for c in range(columns):
            halved = int(kernelsize/2)
            if ((r - halved) >= 0 and (r + halved) < rows): #is in range for filter
                indexOfImage = r - halved
                summed = 0.0
                for i in range(kernelsize):
                    summed += img[indexOfImage][c] * kernel[i]
                    indexOfImage+=1
                verticallyfiltered[r][c]=summed
    return verticallyfiltered

编辑:
为此,建议一次通过图像运行整个内核,因此我重写了该函数(并且它本身仍然可以进行精细的高斯滤波)。我还添加了一个函数来计算给定 X 的高斯(没有 mu,因为 mu=0),所以我可以将我的结果与 Ip-Iq 的高斯相乘。然而,这会导致整个图像变得非常暗 - 这很有意义,高斯函数对于现在很远的像素返回大约 0 的值,因此许多像素是暗的。所以我显然在这里仍然有问题,并希望你们中的一个人能指出我。我试图复制的高斯函数:

和新代码:

def iterate_entirely (kernel=[], img=[], rows=0, columns=0, kernelsize=0, sigma=1.9):
    filtered = img.copy()
    for r in range(rows):
        for c in range(columns):
            halved = int(kernelsize/2)
            if ((c - halved) >= 0 and (c + halved) < columns and (r - halved) >= 0 and (r + halved) < rows): #is in range for filter
                indexOfImageRows = r - halved
                summed = 0.0
                for kr in range(kernelsize):
                    indexOfImageColumns = c - halved
                    for kc in range (kernelsize):
                        ipq = int(img[r][c]) - int(img[indexOfImageRows][indexOfImageColumns])
                        summed += img[indexOfImageRows][indexOfImageColumns] * kernel[kr][kc] * gaussian(ipq, sigma)
                        indexOfImageColumns+=1
                    indexOfImageRows+=1
                filtered[r][c]=summed
    return filtered

def gaussian(x, sigma):
    return 1.0/(numpy.sqrt(2.0*numpy.pi)*sigma)*numpy.exp(-numpy.power((x)/sigma, 2.0)/2)

def gaussian_kernel(kernel_size=3, sigma=1.9):
    x = numpy.linspace(-sigma, sigma, kernel_size+1)
    y = st.norm.cdf(x)
    kernel = numpy.diff(y)
    kernel2d = numpy.outer(kernel, kernel)
    return (kernel2d/kernel2d.sum())

编辑 2:
更多推荐更改,新代码:

def iterate_entirely (kernel=[], img=[], rows=0, columns=0, kernelsize=0, sigma=1.9):
    filtered = img.copy()
    for r in range(rows):
        for c in range(columns):
            halved = int(kernelsize/2)
            if ((c - halved) >= 0 and (c + halved) < columns and (r - halved) >= 0 and (r + halved) < rows): #is in range for filter
                indexOfImageRows = r - halved
                summed = 0.0
                norm = 0.0
                for kr in range(kernelsize):
                    indexOfImageColumns = c - halved
                    for kc in range (kernelsize):
                        ipq = int(img[r][c]) - int(img[indexOfImageRows][indexOfImageColumns])
                        multiplicator = kernel[kr][kc] * gaussian(ipq, sigma)
                        summed += img[indexOfImageRows][indexOfImageColumns] * multiplicator
                        norm += multiplicator
                        indexOfImageColumns+=1
                    indexOfImageRows+=1
                print (" summed: ", summed, " norm: ", norm, " normed : ", summed/norm)
                filtered[r][c]=summed/norm
    return filtered

def gaussian(x, sigma): 
    return numpy.exp(-numpy.power((x)/sigma, 2.0)/2)

【问题讨论】:

  • 考虑在dsp.stackexchange.com上提问
  • “这绝不是一个好的表现”:你是什么意思?该滤波器在边缘保持降噪方面非常有效。如果您的意思是处理时间,请与非本地均值过滤器进行比较!
  • 有趣的是,您确实实现了高斯滤波器,其中出现了Iq,但无法找出Ip-Iq
  • @YvesDaoust 感谢您的回答/ cmets!我对您的实际答案中的澄清做出了反应,所以我不会再在这里这样做了:D 至于性能:是的,我的意思是从时间的角度来看,因为我觉得每个像素迭代两次(每个使用两个 for 循环运行)感觉有点无效。不过,我会研究非本地方式!
  • @CrisLuengo 至于那个,我当然知道我不只是重复(Ip-Iq)。我只是忘了加 G,抱歉。

标签: python image-processing gaussian imagefilter gaussianblur


【解决方案1】:

IpIq 只是pq 的灰度级。 p 处的过滤值主要受空间上靠近它的像素的影响(如在高斯中),但也具有相似的灰度级(在辐射空间中接近)。理由是灰度级差异很大的像素可能来自另一个区域,不应使用。

如果您将图像想象为高度为灰度级的风景,则过滤器输出是与 3D 高斯的卷积,即以目标像素为中心的球体*内的点比外部的权重更大。

[*您可以缩放灰度级,以便衰减在XYI 空间中是各向同性的。]

【讨论】:

  • 感谢您的回答和cmets!因此,如果我理解正确,我需要将像素的结果(对于每个水平和垂直运行)与通过高斯函数运行的结果(Ip-Iq)相乘?根据我的理解,我需要为内核在运行时查看的每个像素计算该值,并且实际上无法调整我拥有的内核,不是吗?
  • @AnnemarieWittig 这个问题的部分答案:你不能使用单独的水平和垂直通道,你必须一次性完成完整的内核。而且你必须为你访问的每个像素更新内核的权重。
  • @CrisLuengo 我在我的问题中添加了一个编辑,因为我将方法更新为我从给定输入中理解的内容。但是,我无法真正让它发挥作用,所以我认为,我没有正确理解您的输入。您能否再次指出我遇到的问题?我非常感谢我已经掌握的东西(至少我现在大致了解该功能)
  • @AnnemarieWittig:我不能说比公式更好。
猜你喜欢
  • 1970-01-01
  • 2021-08-18
  • 1970-01-01
  • 2011-03-17
  • 2013-03-19
  • 2021-04-13
  • 2011-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多