Python 实现双边滤波器

Python 实现双边滤波器,python,algorithm,opencv,computer-vision,dynamic-programming,Python,Algorithm,Opencv,Computer Vision,Dynamic Programming,我正试图从论文中实现一个双边过滤器。实现双边滤波器的方程式(来自论文)如下所示: import cv2 import numpy as np img = cv2.imread("fish.png") # image of width 239 and height 200 bl_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) i = cv2.magnitude( cv2.Sobel(bl_img, cv2.CV_64F, 1, 0, ksi

我正试图从论文中实现一个双边过滤器。实现双边滤波器的方程式(来自论文)如下所示:

import cv2
import numpy as np

img = cv2.imread("fish.png")
# image of width 239 and height 200



bl_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

i = cv2.magnitude(
    cv2.Sobel(bl_img, cv2.CV_64F, 1, 0, ksize=3),
    cv2.Sobel(bl_img, cv2.CV_64F, 0, 1, ksize=3)
)

f = cv2.getGaussianKernel(5, 0.1, cv2.CV_64F)
g = cv2.getGaussianKernel(5, 0.1, cv2.CV_64F)


rows, cols, _ = img.shape

filtered = np.zeros(img.shape, dtype=img.dtype)

for r in range(rows):
    for c in range(cols):
        ks = []
        for index in [-2,-1,1,2]:
            if index + c > 0 and index + c < cols-1:
                p = img[r][index + c]
                s = img[r][c]
                i_p = i[index+c]
                i_s = i[c]
                ks.append(
                    (f * (p-s)) * (g * (i_p * i_s)) # EQUATION 7
                )
        ks = np.sum(np.array(ks))

        js = []
        for index in [-2, -1, 1, 2]:
            if index + c > 0 and index + c < cols -1:
                p = img[r][index + c]
                s = img[r][c]
                i_p = i[index+c]
                i_s = i[c]
                js.append((f * (p-s)) * (g * (i_p * i_s)) * i_p) # EQUATION 6

        js = np.sum(np.asarray(js))
        js = js / ks
        filtered[r][c] = js

cv2.imwrite("f.png", filtered)

据我了解,

  • f是高斯滤波器
  • g是高斯滤波器
  • p是给定图像窗口中的像素
  • s是当前像素
  • Ip是当前像素处的强度
基于此,我编写了实现这些方程的代码,如下所示:

import cv2
import numpy as np

img = cv2.imread("fish.png")
# image of width 239 and height 200



bl_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

i = cv2.magnitude(
    cv2.Sobel(bl_img, cv2.CV_64F, 1, 0, ksize=3),
    cv2.Sobel(bl_img, cv2.CV_64F, 0, 1, ksize=3)
)

f = cv2.getGaussianKernel(5, 0.1, cv2.CV_64F)
g = cv2.getGaussianKernel(5, 0.1, cv2.CV_64F)


rows, cols, _ = img.shape

filtered = np.zeros(img.shape, dtype=img.dtype)

for r in range(rows):
    for c in range(cols):
        ks = []
        for index in [-2,-1,1,2]:
            if index + c > 0 and index + c < cols-1:
                p = img[r][index + c]
                s = img[r][c]
                i_p = i[index+c]
                i_s = i[c]
                ks.append(
                    (f * (p-s)) * (g * (i_p * i_s)) # EQUATION 7
                )
        ks = np.sum(np.array(ks))

        js = []
        for index in [-2, -1, 1, 2]:
            if index + c > 0 and index + c < cols -1:
                p = img[r][index + c]
                s = img[r][c]
                i_p = i[index+c]
                i_s = i[c]
                js.append((f * (p-s)) * (g * (i_p * i_s)) * i_p) # EQUATION 6

        js = np.sum(np.asarray(js))
        js = js / ks
        filtered[r][c] = js

cv2.imwrite("f.png", filtered)
导入cv2
将numpy作为np导入
img=cv2.imread(“fish.png”)
#宽度239和高度200的图像
bl\u img=cv2.CVT颜色(img,cv2.COLOR\u BGR2GRAY)
i=cv2.0量级(
cv2.Sobel(bl_img,cv2.CV_64F,1,0,ksize=3),
cv2.Sobel(bl_img,cv2.CV_64F,0,1,ksize=3)
)
f=cv2.getGaussianKernel(5,0.1,cv2.CV_64F)
g=cv2.getGaussianKernel(5,0.1,cv2.CV_64F)
行,列,u=img.shape
过滤=np.零(img.shape,dtype=img.dtype)
对于范围内的r(行):
对于范围内的c(cols):
ks=[]
对于[-2,-1,1,2]中的索引:
如果索引+c>0且索引+c0且索引+c
但是当我运行这段代码时,我得到一个错误,它说:

    Traceback (most recent call last):
File "bft.py", line 33, in <module>
    (f * (p-s)) * (g * (i_p * i_s))
ValueError: operands could not be broadcast together with shapes (5,3) (5,239) 
回溯(最近一次呼叫最后一次):
文件“bft.py”,第33行,在
(f*(p-s))*(g*(i_p*i_s))
ValueError:操作数无法与形状(5,3)(5239)一起广播

我是否错误地实现了这些等式?我遗漏了什么?

您的代码存在各种问题。最重要的是,这个等式的解释是错误的。f(p-s)表示在p-s处计算函数f。f是高斯分布。同样地,g。代码的部分如下所示:

weight=gaussian(p-s,sigma\u f)*gaussian(i\u p-i\u s,sigma\u g)
ks.附加(重量)
附加(重量*i_p)
请注意,这两个循环可以合并,这样可以避免重复计算
gaussian(x,sigma)
将是一个计算
x
处高斯权重的函数。您需要定义两个sigma,
sigma\u f
sigma\u g
,分别是空间sigma和音调sigma

第二个问题是
p
s
的定义。这些是像素的坐标,而不是像素处图像的值
i_p
i_s
是这些位置的图像值
p-s
基本上是
(r,c)
处的像素与给定邻居之间的空间距离

第三个问题是社区的循环。邻域是所有像素,
高斯(p-s,sigma\u f)
是不可忽略的。因此,邻域的大小取决于所选的
sigma\u f
。你至少应该把它看作是
ceil(2*sigma\u f)
。假设
sigma\u f
为2,则希望邻域从-4变为4(9像素)。但是这个邻域是二维的,不像你的代码中那样是一维的。因此需要两个循环:

适用于范围内的ii(-ceil(2*sigma\u f)、ceil(2*sigma\u f)+1):
如果ii+c>0且ii+c0且jj+r

注意,现在,
p-s
是用
math.sqrt(ii**2+jj**2)
计算的。但还要注意,高斯函数使用
x**2
,因此您可以通过将
x**2
传递到
高斯函数中来跳过平方根的计算。

您的矩阵形状不兼容,不能将一个维数为5,3的矩阵与另一个维数为5的矩阵相乘,239@prhmma你知道对上述方程进行编码的正确方法吗?更改这两行并检查它是否有效
ks.append(np.matmul((f*(p-s)).T,(g*(i_p-i_s)))#方程7
js.append(np.matmul((f*(p-s)).T,(g*(i_p*i_s))*i_p))#方程6
@prhmma不确定这是否是矩阵乘法您需要为高斯核编制索引(或者更好地使用插值)。方程中的f(p-s)意味着在p-s处计算高斯。谢谢您的回答。我正在浏览一个资源,其中描述了实现BF的不同方法。您能给我指一个源吗(或论文)利用邻域的
ceil(2*sigma\u f)
实现BF?如果我向算法提供邻域的值,使得
总邻域!=ceil(2*sigma\u f)
,这意味着什么?@Amanda:原始论文()提出双边滤波器显示了一个例子,其中截止值接近2西格玛(5西格玛为23个像素)。那里的方程显示无限积分(即整个图像域上的求和)。在2西格玛处截止的概念是,高斯函数将具有非常小的值(对于普通高斯滤波,我总是使用至少3西格玛,但双边滤波不需要那么高的精度)@Amanda:在图像的边缘,你会发现邻域中的像素更少。这很好,因为过滤器是标准化的。你总是除以过滤器权重的总和。如果你的问题与使邻域小于2西格玛有关(降低截止值),则效果是空间高斯形状将被截断,导致非高斯形状