如何提高我的爪子检测能力?

     2023-02-23     117

关键词:

【中文标题】如何提高我的爪子检测能力?【英文标题】:How can I improve my paw detection? 【发布时间】:2011-05-04 12:39:55 【问题描述】:

在我上一个关于finding toes within each paw 的问题之后,我开始加载其他测量值,看看它会如何保持。不幸的是,我在前面的一个步骤中很快遇到了问题:识别爪子。

你看,我的概念证明基本上采用了每个传感器的最大压力随着时间的推移,并开始寻找每一行的总和,直到它找到!= 0.0。然后它对列执行相同的操作,并且一旦找到超过 2 行且该行再次为零。它将最小和最大行和列值存储到某个索引。

如图所示,这在大多数情况下都非常有效。但是,这种方法有很多缺点(除了非常原始):

人类可以有“空心脚”,这意味着脚印本身有几行空。因为我担心(大型)狗也会发生这种情况,所以我等了至少 2 到 3 排空行,然后才剪掉了爪子。

如果另一个联系人在到达几个空行之前在不同的列中进行,则会产生问题,从而扩大区域。我想我可以比较这些列,看看它们是否超过某个值,它们必须是单独的爪子。

当狗很小或走得更快时,问题会变得更糟。发生的情况是,前爪的脚趾仍在接触,而后爪的脚趾刚刚开始在与前爪相同的区域内接触!

使用我的简单脚本,它无法拆分这两个,因为它必须确定该区域的哪些帧属于哪个爪子,而目前我只需要查看所有帧的最大值.

开始出错的示例:

所以现在我正在寻找一种更好的方法来识别和分离爪子(之后我将解决决定它是哪只爪子的问题!)。

更新:

我一直在努力实现乔的(真棒!)答案,但我在从我的文件中提取实际爪子数据时遇到了困难。

coded_pa​​ws 显示所有不同的爪子,当应用于最大压力图像时(见上文)。但是,该解决方案会遍历每一帧(以分离重叠的爪子)并设置四个 Rectangle 属性,例如坐标或高度/宽度。

我不知道如何获取这些属性并将它们存储在可以应用于测量数据的某个变量中。因为我需要知道每只爪子的位置,在哪些帧期间它的位置,并将它与它的爪子(前/后,左/右)耦合。

那么如何使用 Rectangles 属性来提取每个爪子的这些值?

我的公共 Dropbox 文件夹中有我在问题设置中使用的测量值(example 1、example 2、example 3)。 For anyone interested I also set up a blog 让您及时了解最新信息 :-)

【问题讨论】:

看起来你必须放弃行/列算法,因为你限制了有用的信息。 哇!猫控制软件? 实际上是狗数据@alxx ;-) 但是,是的,它将用于诊断它们! 为什么? (没关系,不知道更有趣......) 【参考方案1】:

如果您只想要(半)连续区域,Python 中已经有一个简单的实现:SciPy 的ndimage.morphology 模块。这是一个相当常见的image morphology 操作。


基本上,您有 5 个步骤:

def find_paws(data, smooth_radius=5, threshold=0.0001):
    data = sp.ndimage.uniform_filter(data, smooth_radius)
    thresh = data > threshold
    filled = sp.ndimage.morphology.binary_fill_holes(thresh)
    coded_paws, num_paws = sp.ndimage.label(filled)
    data_slices = sp.ndimage.find_objects(coded_paws)
    return object_slices

    稍微模糊输入数据以确保爪子具有连续的足迹。 (只使用更大的内核(structure kwarg 到各种 scipy.ndimage.morphology 函数)会更有效,但由于某种原因这不能正常工作......)

    对数组设置阈值,以便您拥有一个布尔数组,其中包含压力超过某个阈值的位置(即thresh = data > value

    填充所有内部孔,使区域更清洁 (filled = sp.ndimage.morphology.binary_fill_holes(thresh))

    找到单独的连续区域 (coded_paws, num_paws = sp.ndimage.label(filled))。这将返回一个数组,其中的区域由数字编码(每个区域都是一个唯一整数的连续区域(从 1 到爪子的数量),其他地方都是零)。

    使用data_slices = sp.ndimage.find_objects(coded_paws) 隔离连续区域。这将返回slice 对象的元组列表,因此您可以使用[data[x] for x in data_slices] 获取每个爪子的数据区域。相反,我们将根据这些切片绘制一个矩形,这需要更多的工作。


下面的两个动画显示了您的“重叠爪子”和“分组爪子”示例数据。这种方法似乎工作得很好。 (不管它值多少钱,这比我机器上的下面的 GIF 图像运行得更流畅,所以爪子检测算法相当快......)


这是一个完整的例子(现在有更详细的解释)。其中绝大多数是读取输入并制作动画。实际的爪子检测只有 5 行代码。

import numpy as np
import scipy as sp
import scipy.ndimage

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

def animate(input_filename):
    """Detects paws and animates the position and raw data of each frame
    in the input file"""
    # With matplotlib, it's much, much faster to just update the properties
    # of a display object than it is to create a new one, so we'll just update
    # the data and position of the same objects throughout this animation...

    infile = paw_file(input_filename)

    # Since we're making an animation with matplotlib, we need 
    # ion() instead of show()...
    plt.ion()
    fig = plt.figure()
    ax = fig.add_subplot(111)
    fig.suptitle(input_filename)

    # Make an image based on the first frame that we'll update later
    # (The first frame is never actually displayed)
    im = ax.imshow(infile.next()[1])

    # Make 4 rectangles that we can later move to the position of each paw
    rects = [Rectangle((0,0), 1,1, fc='none', ec='red') for i in range(4)]
    [ax.add_patch(rect) for rect in rects]

    title = ax.set_title('Time 0.0 ms')

    # Process and display each frame
    for time, frame in infile:
        paw_slices = find_paws(frame)

        # Hide any rectangles that might be visible
        [rect.set_visible(False) for rect in rects]

        # Set the position and size of a rectangle for each paw and display it
        for slice, rect in zip(paw_slices, rects):
            dy, dx = slice
            rect.set_xy((dx.start, dy.start))
            rect.set_width(dx.stop - dx.start + 1)
            rect.set_height(dy.stop - dy.start + 1)
            rect.set_visible(True)

        # Update the image data and title of the plot
        title.set_text('Time %0.2f ms' % time)
        im.set_data(frame)
        im.set_clim([frame.min(), frame.max()])
        fig.canvas.draw()

def find_paws(data, smooth_radius=5, threshold=0.0001):
    """Detects and isolates contiguous regions in the input array"""
    # Blur the input data a bit so the paws have a continous footprint 
    data = sp.ndimage.uniform_filter(data, smooth_radius)
    # Threshold the blurred data (this needs to be a bit > 0 due to the blur)
    thresh = data > threshold
    # Fill any interior holes in the paws to get cleaner regions...
    filled = sp.ndimage.morphology.binary_fill_holes(thresh)
    # Label each contiguous paw
    coded_paws, num_paws = sp.ndimage.label(filled)
    # Isolate the extent of each paw
    data_slices = sp.ndimage.find_objects(coded_paws)
    return data_slices

def paw_file(filename):
    """Returns a iterator that yields the time and data in each frame
    The infile is an ascii file of timesteps formatted similar to this:

    Frame 0 (0.00 ms)
    0.0 0.0 0.0
    0.0 0.0 0.0

    Frame 1 (0.53 ms)
    0.0 0.0 0.0
    0.0 0.0 0.0
    ...
    """
    with open(filename) as infile:
        while True:
            try:
                time, data = read_frame(infile)
                yield time, data
            except StopIteration:
                break

def read_frame(infile):
    """Reads a frame from the infile."""
    frame_header = infile.next().strip().split()
    time = float(frame_header[-2][1:])
    data = []
    while True:
        line = infile.next().strip().split()
        if line == []:
            break
        data.append(line)
    return time, np.array(data, dtype=np.float)

if __name__ == '__main__':
    animate('Overlapping paws.bin')
    animate('Grouped up paws.bin')
    animate('Normal measurement.bin')

更新:至于识别哪个爪子在什么时间与传感器接触,最简单的解决方案是只进行相同的分析,但同时使用所有数据。 (即将输入堆叠到 3D 数组中,并使用它,而不是单独的时间帧。)因为 SciPy 的 ndimage 函数旨在使用 n 维数组,我们不必修改原始的爪子查找函数完全没有。

# This uses functions (and imports) in the previous code example!!
def paw_regions(infile):
    # Read in and stack all data together into a 3D array
    data, time = [], []
    for t, frame in paw_file(infile):
        time.append(t)
        data.append(frame)
    data = np.dstack(data)
    time = np.asarray(time)

    # Find and label the paw impacts
    data_slices, coded_paws = find_paws(data, smooth_radius=4)

    # Sort by time of initial paw impact... This way we can determine which
    # paws are which relative to the first paw with a simple modulo 4.
    # (Assuming a 4-legged dog, where all 4 paws contacted the sensor)
    data_slices.sort(key=lambda dat_slice: dat_slice[2].start)

    # Plot up a simple analysis
    fig = plt.figure()
    ax1 = fig.add_subplot(2,1,1)
    annotate_paw_prints(time, data, data_slices, ax=ax1)
    ax2 = fig.add_subplot(2,1,2)
    plot_paw_impacts(time, data_slices, ax=ax2)
    fig.suptitle(infile)

def plot_paw_impacts(time, data_slices, ax=None):
    if ax is None:
        ax = plt.gca()

    # Group impacts by paw...
    for i, dat_slice in enumerate(data_slices):
        dx, dy, dt = dat_slice
        paw = i%4 + 1
        # Draw a bar over the time interval where each paw is in contact
        ax.barh(bottom=paw, width=time[dt].ptp(), height=0.2, 
                left=time[dt].min(), align='center', color='red')
    ax.set_yticks(range(1, 5))
    ax.set_yticklabels(['Paw 1', 'Paw 2', 'Paw 3', 'Paw 4'])
    ax.set_xlabel('Time (ms) Since Beginning of Experiment')
    ax.yaxis.grid(True)
    ax.set_title('Periods of Paw Contact')

def annotate_paw_prints(time, data, data_slices, ax=None):
    if ax is None:
        ax = plt.gca()

    # Display all paw impacts (sum over time)
    ax.imshow(data.sum(axis=2).T)

    # Annotate each impact with which paw it is
    # (Relative to the first paw to hit the sensor)
    x, y = [], []
    for i, region in enumerate(data_slices):
        dx, dy, dz = region
        # Get x,y center of slice...
        x0 = 0.5 * (dx.start + dx.stop)
        y0 = 0.5 * (dy.start + dy.stop)
        x.append(x0); y.append(y0)

        # Annotate the paw impacts         
        ax.annotate('Paw %i' % (i%4 +1), (x0, y0),  
            color='red', ha='center', va='bottom')

    # Plot line connecting paw impacts
    ax.plot(x,y, '-wo')
    ax.axis('image')
    ax.set_title('Order of Steps')



【讨论】:

我什至无法解释你的回答有多棒! @Ivo:是的,我也很乐意再给 Joe 投票 :) 但我应该开始一个新问题,或者@Joe,如果你愿意,可以在这里回答吗? ***.com/questions/2546780/… 我实际上只是丢弃了 .png 文件,并做了一个 convert *.png output.gif。我之前确实让 imagemagick 让我的机器崩溃了,尽管它在这个例子中运行良好。过去,我使用此脚本:svn.effbot.python-hosting.com/pil/Scripts/gifmaker.py 直接从 python 编写动画 gif,而不保存单个帧。希望有帮助!我将在@unutbu 提到的问题上发布一个示例。 感谢@Joe 提供的信息。我的部分问题是忽略在plt.savefig 中使用bbox_inches='tight',另一个是不耐烦:) 天哪,我只想说 这个答案太棒了。【参考方案2】:

我不是图像检测方面的专家,也不懂 Python,但我会试一试...

要检测单个爪子,您应该首先只选择压力大于某个小阈值的所有内容,非常接近于没有压力。高于此的每个像素/点都应该被“标记”。然后,与所有“标记”像素相邻的每个像素都被标记,并且此过程重复几次。将形成完全连接的质量,因此您有不同的对象。然后,每个“对象”都有一个最小和最大 x 和 y 值,因此边界框可以整齐地包装在它们周围。

伪代码:

(MARK) ALL PIXELS ABOVE (0.5)

(MARK) ALL PIXELS (ADJACENT) TO (MARK) PIXELS

REPEAT (STEP 2) (5) TIMES

SEPARATE EACH TOTALLY CONNECTED MASS INTO A SINGLE OBJECT

MARK THE EDGES OF EACH OBJECT, AND CUT APART TO FORM SLICES.

应该差不多了。

【讨论】:

【参考方案3】:

注意:我说的是像素,但这可能是使用像素平均值的区域。优化是另一个问题...

听起来您需要分析每个像素的函数(压力随时间变化)并确定where the function turns(当它在另一个方向上改变 > X 时,它被视为转向反错误)。

如果您知道它在哪个帧转动,您就会知道压力最大的帧,以及两只爪子之间压力最小的帧。理论上,您将知道爪子最用力按压的两个帧,并可以计算出这些间隔的平均值。

之后我将解决决定它是哪只爪子的问题!

这与以前的游览相同,知道每只爪子何时施加最大压力有助于您做出决定。

【讨论】:

目标检测如何提高网络的特征提取能力

参考技术A1,通过对输入数据的手动查验或自动化统计,确定较好的canny阈值2,利用阈值对训练样本中10-20个batch的数据进行canny边缘增强3,增强方式为:原图转灰度提取到的canny边缘所对应的原图像素位置进行对比度增强或直接... 查看详情

检测机构服务平台助力检测机构提高检测能力

...与时俱进,及时的学习和关注最新资料,这样才能更好的提高技术人员的检测水平,整体提升检验检测机构的检测能力。  但是伴随而来的突出问题是,检验检测技术人员在查找相关资料的时候,总是不能找到很好的平台来随... 查看详情

如何提高英文的科研写作能力

作为一个科研工作者,在国际学术期刊上发表科研论文是与同行交流、取得国际影响的必经之路。有些国内的科学家,实验做得很漂亮,但常常苦恼于论文的写作力不从心,成为国际交流的一大障碍。本文从博主... 查看详情

如何提高表达能力

...按成分来说有:主语、谓语、宾语2、常用的连接词?3、如何排列组合脑海中的关键词?4、如何概括一件事?5、训练表达能力的方法  1)自问自答并录音  2)罗列一些场景,思考在不同的场景该说什么话  3)模仿:模... 查看详情

理解能力能提高吗?

?什么是理解力??如何促进思考??如何促进整合?声明:此文是建立在你已经了解如何思考和学习的本质的基础上,进一步探讨如何提高理解能力。(如果想了解“思考”和“学习的本质”,可以看这两篇:我何尝不想主动思考... 查看详情

设计师如何提高个人的色彩搭配能力?

...为了帮助更多的设计小白快速提高配色能力,分享设计师如何提高色彩搭配能力?  1、多看多接触  这里说的多看多接触,其实就是让大家多接受优秀作品的熏陶, 查看详情

如何提高 Blob 检测精度?

】如何提高Blob检测精度?【英文标题】:HowtoImproveBlobsDetectionAccuracy?【发布时间】:2012-02-1617:34:00【问题描述】:考虑下图:它是一段视频中的一个帧,视频中的几个人互相交谈。我试图对该视频进行斑点检测,但是当两个人彼... 查看详情

如何提高自我学习能力?

 一、学习综述由于人类的记忆能力有限,无法记住大规模的细节信息,所以需要对信息进行压缩与高度概括。于是文字诞生了,文字是对客观事物的抽象表达,本质是信息压缩,分为表音、表形、表意三种,它是人类的学习... 查看详情

如何检测文本文件的实时变化?

】如何检测文本文件的实时变化?【英文标题】:Howtodetectreal-timechangeoftextfiles?【发布时间】:2012-11-0120:54:53【问题描述】:我说要编写一个小的PC工具来使用c#或java读取日志文件。日志文件将采用.txt格式。一个应用程序正在运... 查看详情

客户端检测

...识别浏览器的能力。采用这种方式不必顾及特定的浏览器如何如何,只要确定浏览器支持特定的能力,就可以给出解决方案。能力检测的理想代码:functionisHostMethod(object,property){vart=typeofob 查看详情

学生如何提高专业英文阅读能力

【序:此文针对本科生和一、二年级的博士、硕士生,对高年级的博士生和博士后也应该有参考价值。该文的一些背景可以参考我此前关于提高英文写作能力的博文:http://www.sciencenet.cn/m/user_content.aspx?id=349932】 从... 查看详情

编程新手如何提高编程能力?

...步入程序员大军的小萌新/程序员界的老司机,你们都是如何备战大厂的呢?是否面对网络上纷繁复杂的资料茫然无从下手?抑或是坐在电脑旁埋头敲着代码却找不到一丝存在感?不用怕!今天我就来带大家一起解锁一款程序员... 查看详情

如何提高编程能力?

其实很多人学编程都会遇到困难,我觉得其中一个根本原因是他们没搞明白学编程到底是学什么。 编程不是一种知识,而是一门手艺。 我们从小到大的学习都是学习知识,流程一般是课前看书预习,上课听讲,下课做作... 查看详情

如何旋转 3D 阵列?

】如何旋转3D阵列?【英文标题】:HowcanIrotatea3Darray?【发布时间】:2011-06-1312:20:47【问题描述】:目前,如果我想比较狗的每个爪子下的压力,我只比较每个脚趾下的压力。但我想尝试比较整个爪子下方的压力。但要这样做,我... 查看详情

如何快速提高编程能力(代码片段)

#############################################"""如何快速提高编程能力,自己的认识1,多练,这是每一个人都知道的,2,多学,学习别人的代码""" #############################################"""别人总结的方法:第一条,多写一定要多练,多写... 查看详情

如何提高编程能力

1. 多写代码学习某件事情最好的办法就是练习。你应该花大量时间去构建和编写代码除非你认为练习对你的帮助不大。你可以从写一些基础知识相关的简单程序开始。2. 参与不同类型的项目当你对某种开发语言非常熟悉... 查看详情

如何使用 CSS 将视频向右移动 - 以提高响应能力?

】如何使用CSS将视频向右移动-以提高响应能力?【英文标题】:HowdoIshiftavideototherightwithCSS-forresponsiveness?【发布时间】:2021-12-1703:16:54【问题描述】:因此,对于大于1080像素的任何页面,此视频都非常适合,但在768像素和1080像... 查看详情

如何在 android 中提高 OpenCV 人脸检测性能?

】如何在android中提高OpenCV人脸检测性能?【英文标题】:HowtoimproveOpenCVfacedetectionperformanceinandroid?【发布时间】:2015-02-2006:20:55【问题描述】:我正在开发一个android项目,在该项目中我使用OpenCV从图库中的所有图像中检测人脸。... 查看详情