饮歌长啸
解数据文件:paw.txt。源代码:from scipy import *from operator import itemgetter
n = 5 # how many fingers are we looking ford = loadtxt("paw.txt")width, height = d.shape# Create an array where every element is a sum of 2x2 squares.fourSums = d[:-1,:-1] + d[1:,:-1] + d[1:,1:] + d[:-1,1:]# Find positions of the fingers.# Pair each sum with its position number (from 0 to width*height-1),pairs = zip(arange(width*height), fourSums.flatten())# Sort by descending sum value, filter overlapping squaresdef drop_overlapping(pairs):
no_overlaps = []
def does_not_overlap(p1, p2):
i1, i2 = p1[0], p2[0]
r1, col1 = i1 / (width-1), i1 % (width-1)
r2, col2 = i2 / (width-1), i2 % (width-1)
return (max(abs(r1-r2),abs(col1-col2)) >= 2)
for p in pairs:
if all(map(lambda prev: does_not_overlap(p,prev), no_overlaps)):
no_overlaps.append(p)
return no_overlaps
pairs2 = drop_overlapping(sorted(pairs, key=itemgetter(1), reverse=True))# Take the first n with the heighest valuespositions = pairs2[:n]# Print resultsprint d, "\n"for i, val in positions:
row = i / (width-1)
column = i % (width-1)
print "sum = %f @ %d,%d (%d)" % (val, row, column, i)
print d[row:row+2,column:column+2], "\n"输出没有重叠方块。似乎在您的示例中选择了相同的区域。一些评论棘手的部分是计算所有2x2平方的总和。我假设你需要所有这些,所以可能会有一些重叠。我使用切片从原始2D数组中剪切第一个/最后一个列和行,然后将它们重叠在一起并计算总和。为了更好地理解它,对3x3阵列进行成像:>>> a = arange(9).reshape(3,3) ; a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])然后你可以拿它的切片:>>> a[:-1,:-1]array([[0, 1],
[3, 4]])>>> a[1:,:-1]array([[3, 4],
[6, 7]])>>> a[:-1,1:]array([[1, 2],
[4, 5]])>>> a[1:,1:]array([[4, 5],
[7, 8]])现在想象一下,将它们叠加在另一个之上,并将元素加在相同位置。这些总和与2x2正方形的总和相同,左上角位于同一位置:>>> sums = a[:-1,:-1] + a[1:,:-1] + a[:-1,1:] + a[1:,1:]; sums
array([[ 8, 12],
[20, 24]])当你有过的2x2平方的总和,可以使用max以找到最大,或者sort,或者sorted找到峰值。为了记住峰值的位置,我将每个值(总和)与其在平顶阵列中的序数位置耦合(参见参考资料zip)。然后我打印结果时再次计算行/列位置。笔记我允许2x2方格重叠。编辑版本过滤掉其中一些版本,使得结果中仅出现非重叠的正方形。选择手指(一个想法)另一个问题是如何从所有峰中选择可能是手指的东西。我有一个想法可能会或可能不会奏效。我现在没时间实现它,所以只是伪代码。我注意到如果前手指几乎保持完美的圆形,则后指应位于该圆圈的内侧。而且,前指或多或少地等间隔。我们可能会尝试使用这些启发式属性来检测手指。伪代码:select the top N finger candidates (not too many, 10 or 12)consider all possible combinations of 5 out of N (use itertools.combinations)for each combination of 5 fingers:
for each finger out of 5:
fit the best circle to the remaining 4
=> position of the center, radius
check if the selected finger is inside of the circle
check if the remaining four are evenly spread (for example, consider angles from the center of the circle)
assign some cost (penalty) to this selection of 4 peaks + a rear finger (consider, probably weighted:
circle fitting error,
if the rear finger is inside,
variance in the spreading of the front fingers,
total intensity of 5 peaks)choose a combination of 4 peaks + a rear peak with the lowest penalty这是一种蛮力的方法。如果N相对较小,那么我认为它是可行的。对于N = 12,有C_12 ^ 5 = 792种组合,有5种方式可以选择一个后指,所以3960个案例来评估每个爪子。