这是一个棘手的问题,因为您需要仔细定义最大值或最小值在何时才算是相关的“大”。例如,想象一下,您有一个包含以下5x5像素网格的补丁:
im = np.array([[ 0 0 0 0 0
0 5 5 5 0
0 5 4 5 0
0 5 5 5 0
0 0 0 0 0. ]])
这可能被视为局部最小值,因为4比周围的5要小。另一方面,它也可能被看作是局部最大值,其中单独的4像素只是“噪声”,而平均强度为4.89的3x3补丁实际上是一个单一的局部最大值。这通常被称为您正在查看图像的“比例尺”。
无论如何,您可以通过在该方向上使用有限差分来估计一个方向上的局部导数。例如,“x”方向可能是这样的:
k = np.array([[ -1 0 1
-1 0 1
-1 0 1. ]])
将此滤镜应用于上述定义的图像补丁,结果如下:
>>> cv2.filter2D(im, cv2.CV_64F, k)[1:-1,1:-1]
array([[ 9., 0., -9.],
[ 14., 0., -14.],
[ 9., 0., -9.]])
应用类似的过滤器在y方向上会转置。这里唯一一个x和y方向都为0的点是我们决定是局部最小值的中心点,也就是数字4。这相当于检查梯度在x和y方向上是否为0。
整个过程可以扩展到找到我们已经确定的更大的单一局部最大值。您将使用一个更大的过滤器,例如。
k = np.array([[ -2, -1, 0, 1, 2],
[ -2, -1, 0, 1, 2], ...
由于4使局部最大值变成近似值,因此您需要使用一些“近似”逻辑。也就是说,您将寻找接近0的值。接近程度取决于您愿意允许局部极值有多少模糊性。总之,在这里有两个模糊因素:1.过滤器大小和2.~=0的模糊因素。