我正在帮助兽医诊所测量狗爪下的压力。我使用Python进行数据分析,现在我被困在试图将爪子分成(解剖)子区域。
我制作了每个爪子的2D数组,其中包含爪子随时间推移已加载的每个传感器的最大值。这是一个爪子的示例,我使用Excel绘制了要“检测”的区域。这些是传感器周围具有最大最大值的2 x 2框,它们的总和最大。
因此,我尝试了一些实验,并决定只寻找每一列和每一行的最大值(由于爪子的形状而无法朝一个方向看)。这似乎可以很好地“检测”到各个脚趾的位置,但是它也标记了相邻的传感器。
那么,告诉Python我想要的最大最大值是什么?
注意:2x2的正方形不能重叠,因为它们必须是单独的脚趾!
同样我以2x2为方便,欢迎使用任何更高级的解决方案,但我只是人类运动的科学家,所以我既不是真正的程序员也不是数学家,所以请保持“简单”。
这是可以加载的版本np.loadtxt
结果 因此,我尝试了@jextee的解决方案(请参见下面的结果)。如您所见,它在前爪上非常有效,但在后腿上效果较差。
更具体地说,它无法识别出第四脚趾的小峰。显然,这是回路从上向下朝着最低值而不考虑这在哪里的事实所固有的。
谁会知道如何调整@jextee的算法,以便它也能够找到第四个脚趾?
由于我尚未处理其他任何试验,因此无法提供任何其他样品。但是我之前提供的数据是每只爪子的平均值。该文件是一个数组,其中最大9爪的数据按它们与板接触的顺序排列。
此图显示了它们如何在空间上分布在板上。
新更新: 因此,在获得有关爪子检测和爪子分类的问题的帮助后,我终于能够检查每个爪子的脚趾检测!事实证明,除了爪子大小像我自己的示例中的爪子一样,它在任何情况下都无法正常工作。事后看来,如此随意地选择2x2是我自己的错。
这是一个出问题的好例子:指甲被识别为脚趾,而“脚跟”是如此之宽,被识别两次!
脚掌太大,因此采用2x2大小且没有重叠的脚掌会使两次脚趾被检测到两次。相反,在小型犬中,它通常找不到第5个脚趾,我怀疑这是2x2区域太大造成的。
在尝试了所有解决方案的最新解决方案后,我得出了一个惊人的结论:几乎对我所有的小型犬来说,它都找不到第五个脚趾,而在大型犬的50%以上的撞击中,它会发现更多!
所以很明显我需要更改它。我自己的猜测是将大小更改neighborhood为小型犬较小,大型犬较大。但是generate_binary_structure不允许我更改数组的大小。
neighborhood
generate_binary_structure
因此,我希望其他人对脚趾的定位有更好的建议,也许脚趾的面积与爪子的大小成正比?
我使用局部最大滤波器检测到峰值。这是第一个4个爪子的数据集的结果:
我还在9个爪子的第二个数据集上运行了它,效果也很好。
这是你的操作方式:
import numpy as np from scipy.ndimage.filters import maximum_filter from scipy.ndimage.morphology import generate_binary_structure, binary_erosion import matplotlib.pyplot as pp #for some reason I had to reshape. Numpy ignored the shape header. paws_data = np.loadtxt("paws.txt").reshape(4,11,14) #getting a list of images paws = [p.squeeze() for p in np.vsplit(paws_data,4)] def detect_peaks(image): """ Takes an image and detect the peaks usingthe local maximum filter. Returns a boolean mask of the peaks (i.e. 1 when the pixel's value is the neighborhood maximum, 0 otherwise) """ # define an 8-connected neighborhood neighborhood = generate_binary_structure(2,2) #apply the local maximum filter; all pixel of maximal value #in their neighborhood are set to 1 local_max = maximum_filter(image, footprint=neighborhood)==image #local_max is a mask that contains the peaks we are #looking for, but also the background. #In order to isolate the peaks we must remove the background from the mask. #we create the mask of the background background = (image==0) #a little technicality: we must erode the background in order to #successfully subtract it form local_max, otherwise a line will #appear along the background border (artifact of the local maximum filter) eroded_background = binary_erosion(background, structure=neighborhood, border_value=1) #we obtain the final mask, containing only peaks, #by removing the background from the local_max mask (xor operation) detected_peaks = local_max ^ eroded_background return detected_peaks #applying the detection and plotting results for i, paw in enumerate(paws): detected_peaks = detect_peaks(paw) pp.subplot(4,2,(2*i+1)) pp.imshow(paw) pp.subplot(4,2,(2*i+2) ) pp.imshow(detected_peaks) pp.show()
你需要做的就是scipy.ndimage.measurements.label在蒙版上使用以标记所有不同的对象。这样你就可以分别与他们一起玩了。
scipy.ndimage.measurements.label
请注意,该方法效果很好,因为背景不嘈杂。如果是这样,你将在背景中检测到许多其他不需要的峰。另一个重要因素是邻里的大小。如果峰大小发生变化,则需要对其进行调整(应保持大致成比例)。