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