opencv 几何均值滤波器
Geometric mean filter with opencv
我想在 opencv (python) 中对图像应用几何平均滤波器。有内置函数还是我应该自己实现过滤器?在 opencv 中实现非线性滤波器的最有效方法是什么?
从对数恒等式回想一下
log((x1 * x2 * ... * xn)^(1/n)) = (1/n) * (log(x1) + log(x2) + ... + log(xn))
来自Wikipedia:
The geometric mean can also be expressed as the exponential of the arithmetic mean of logarithms. By using logarithmic identities to transform the formula, the multiplications can be expressed as a sum and the power as a multiplication.
这意味着几何平均值可以简单地计算为算术平均值,即图像值的对数 cv2.boxFilter()
。然后你只需对结果取幂就可以了!
例如,让我们测试手动方法和此方法并检查结果。首先加载图像并定义内核大小:
import cv2
import numpy as np
img = cv2.imread('cameraman.png', cv2.IMREAD_GRAYSCALE).astype(float)
rows, cols = img.shape[:2]
ksize = 5
接下来让我们填充图像并手动计算几何平均值:
padsize = int((ksize-1)/2)
pad_img = cv2.copyMakeBorder(img, *[padsize]*4, cv2.BORDER_DEFAULT)
geomean1 = np.zeros_like(img)
for r in range(rows):
for c in range(cols):
geomean1[r, c] = np.prod(pad_img[r:r+ksize, c:c+ksize])**(1/(ksize**2))
geomean1 = np.uint8(geomean1)
cv2.imshow('1', geomean1)
cv2.waitKey()
看起来符合我们的预期。现在不是这样,如果我们使用对数版本,我们需要做的就是在图像的对数上取盒式滤波器的指数运行:
geomean2 = np.uint8(np.exp(cv2.boxFilter(np.log(img), -1, (ksize, ksize))))
cv2.imshow('2', geomean2)
cv2.waitKey()
嗯,它们看起来确实一样。其实我作弊了,这是和上面上传的一样的图片。但这没关系,因为:
print(np.array_equal(geomean1, geomean2))
True
我想在 opencv (python) 中对图像应用几何平均滤波器。有内置函数还是我应该自己实现过滤器?在 opencv 中实现非线性滤波器的最有效方法是什么?
从对数恒等式回想一下
log((x1 * x2 * ... * xn)^(1/n)) = (1/n) * (log(x1) + log(x2) + ... + log(xn))
来自Wikipedia:
The geometric mean can also be expressed as the exponential of the arithmetic mean of logarithms. By using logarithmic identities to transform the formula, the multiplications can be expressed as a sum and the power as a multiplication.
这意味着几何平均值可以简单地计算为算术平均值,即图像值的对数 cv2.boxFilter()
。然后你只需对结果取幂就可以了!
例如,让我们测试手动方法和此方法并检查结果。首先加载图像并定义内核大小:
import cv2
import numpy as np
img = cv2.imread('cameraman.png', cv2.IMREAD_GRAYSCALE).astype(float)
rows, cols = img.shape[:2]
ksize = 5
接下来让我们填充图像并手动计算几何平均值:
padsize = int((ksize-1)/2)
pad_img = cv2.copyMakeBorder(img, *[padsize]*4, cv2.BORDER_DEFAULT)
geomean1 = np.zeros_like(img)
for r in range(rows):
for c in range(cols):
geomean1[r, c] = np.prod(pad_img[r:r+ksize, c:c+ksize])**(1/(ksize**2))
geomean1 = np.uint8(geomean1)
cv2.imshow('1', geomean1)
cv2.waitKey()
看起来符合我们的预期。现在不是这样,如果我们使用对数版本,我们需要做的就是在图像的对数上取盒式滤波器的指数运行:
geomean2 = np.uint8(np.exp(cv2.boxFilter(np.log(img), -1, (ksize, ksize))))
cv2.imshow('2', geomean2)
cv2.waitKey()
嗯,它们看起来确实一样。其实我作弊了,这是和上面上传的一样的图片。但这没关系,因为:
print(np.array_equal(geomean1, geomean2))
True