我正在尝试从论文快速双边过滤中实现双边过滤器,以显示高动态范围图像。实现双边滤波器的方程(来自本文)为:
据我了解,
这样,我编写了实现这些方程的代码,如下所示:
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)
但是,当我运行此代码时,我收到一条错误消息:
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)
我是否错误地实现了方程式?我想念什么?
您的代码存在各种问题。最重要的是,该方程的解释方式有误。f(ps)表示在ps处评估函数f。f是高斯。同样与克。代码部分如下所示:
weight = gaussian(p - s, sigma_f) * gaussian(i_p - i_s, sigma_g)
ks.append(weight)
js.append(weight * i_p)
注意,两个循环可以合并,这样可以避免重复计算。gaussian(x, sigma)
将是一个函数,计算处的高斯权重x
。您需要分别定义两个sigma_f
和sigma_g
,分别是和和。
第二个问题是p
and的定义s
。这些是像素的坐标,而不是像素处图像的值。i_p
和i_s
是图像的在那些位置的值。p-s
基本上是像素(r,c)
与给定邻居之间的空间距离。
第三个问题是邻居之间的循环。邻域是gaussian(p - s, sigma_f)
不可忽略的所有像素。因此,邻域的大小取决于所选的sigma_f
。你至少应该把它当做ceil(2*sigma_f)
。假设sigma_f
为2,则您希望邻域从-4变为4(9像素)。但是,该邻域是二维的,而不是代码中的一维的。因此,您需要两个循环:
for ii in range(-ceil(2*sigma_f), ceil(2*sigma_f)+1):
if ii + c > 0 and ii + c < cols-1:
for jj in range(-ceil(2*sigma_f), ceil(2*sigma_f)+1):
if jj + r > 0 and jj + r < rows-1:
# compute weight here
请注意,现在p-s
是使用计算的math.sqrt(ii**2 + jj**2)
。但也请注意,高斯使用x**2
,因此您可以通过传递x**2
给gaussian
函数来跳过平方根的计算。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句