我有一个大的三维numpy数组(1024 x 1024 x 1024),需要找到局部极大值周围的区域,使得所有值大于局部最大值50%的相邻点都被递归地聚集在同一区域内。可以使用迭代算法来解决:
具体而言,对于像这样的二维数组:
直观地说,我正在寻找局部极大值周围的“山脉”,其中“山脉”由轮廓级别定义,该级别不是绝对的而是相对于局部极大值。
我已经尝试使用scipy.ndimage来查找局部最大值,这非常有用。但是我不知道如何获取它们周围的区域。我还查看了标准聚类算法和图像处理技术,例如斑点检测或本地阈值处理,但似乎没有一个能够重现这个问题。
感谢您的建议。
提前致谢,
编辑:感谢taw,下面是一个解决方案。
- 从最高值到最低值循环遍历局部最大值。
- 如果该局部最大值已经分配给某个区域,则跳过并继续循环遍历下一个局部最大值。
- 如果该局部最大值未分配给任何区域,则将其分配给新区域。将该局部最大值的值设为M。
- 添加所有值>0.5*M的局部最大值的相邻点到该区域中。
- 递归添加所有值>0.5*M的相邻点、相邻点的相邻点......到该区域中。
- 重复执行,直到所有局部最大值都被分配给某个区域。
具体而言,对于像这样的二维数组:
0.0 1.6 0.0 0.0 0.0
0.0 2.0 1.0 0.0 5.0
1.6 3.0 1.0 0.0 4.6
0.0 0.0 0.0 9.0 4.6
将会有两个这样的区域:
5.0
4.6
9.0 4.6
并且
1.6
2.0
1.6 3.0
直观地说,我正在寻找局部极大值周围的“山脉”,其中“山脉”由轮廓级别定义,该级别不是绝对的而是相对于局部极大值。
我已经尝试使用scipy.ndimage来查找局部最大值,这非常有用。但是我不知道如何获取它们周围的区域。我还查看了标准聚类算法和图像处理技术,例如斑点检测或本地阈值处理,但似乎没有一个能够重现这个问题。
感谢您的建议。
提前致谢,
编辑:感谢taw,下面是一个解决方案。
import math
import numpy as np
def soln(data, maxind):
test = np.pad(data,(1,1),'constant',constant_values = [-math.inf,-math.inf])
regionlist = {} # Dictionary with the results
for region, ind in enumerate(maxind): # Loop over all maxima
M = test[ind[0]+1, ind[1]+1, ind[2]+1] # Value of the maximum
if M == -np.inf:
continue
regionlist[region] = set()
regionlist[region].add(ind)
test[ind[0]+1, ind[1]+1, ind[2]+1] = -math.inf # All points that are added to the results are set to -infinity
neighbors = set()
neighbors.add((ind[0]+1, ind[1]+1, ind[2]+1))
while len(neighbors)>0: #create region iteratively
newneighbors = set() # This will contain the new elements in the region
for i in neighbors:
values = test[i[0]-1:i[0]+2, i[1]-1:i[1]+2, i[2]-1:i[2]+2] # Values of neighbours
valuesmask = values > .5*M # Neighbours that fall in region
list1 = range(i[0]-2, i[0]+1)
list2 = range(i[1]-2, i[1]+1)
list3 = range(i[2]-2, i[2]+1)
indlist = list(itertools.product(list1, list2, list3)) # 3-D list with coordinates of neighbours
for count,j in enumerate(valuesmask):
if j:
newneighbors.add(indlist[count])
#update iteration
newneighbors = newneighbors.difference(neighbors) # Remove all elements that were already iterated over and added to regionlist
regionlist[region].update(newneighbors) # Add the new elements in the region to regionlist
neighbors = set((x[0]-1, x[1]-1, x[2]-1) for x in newneighbors) # In the next iteration, iterate only over new elements in the region
for i in newneighbors:
test[i[0]+1, i[1]+1, i[2]+1] = -math.inf #set values to -inf after added to region
return regionlist
scipy.ndimage.maximum_filter
获取局部最大值(大于所有最近邻点的点),就像这个问题中所示。我已经更新了问题,加入了正确的三维扩展和一个小错误修复:我认为,在你的例子中,neighbors
包含了data
数组中点的坐标,而根据循环它应该包含test
数组中的坐标。 - IvFrat