【问题标题】:Simple object recognition简单的物体识别
【发布时间】:2010-11-29 18:23:37
【问题描述】:

===已解决===

感谢您的建议和 cmets。通过研究Beginning Python Visualization book(第 9 章 - 图像处理)中给出的 flood_fill 算法,我已经实现了我想要的。我可以计算对象,获取每个对象的封闭矩形(因此是高度和宽度),最后可以为每个对象构造 NumPy 数组或矩阵。

虽然它不是一种优化的方法,但它可以满足我的需求。我使用的源代码(lab2.py)和png文件(lab2-particles.png)已经放在http://code.google.com/p/ccnworks/source/browse/#svn/trunk/AtSc450下。

您需要安装 NumPy 和 PIL,并使用 matplotlib 来查看直方图。代码的核心位于 objfind 函数中,主要的递归对象搜索动作发生在该函数中。

进一步更新:

SciPy 的 ndimage.label() 也完全符合我的要求。

为 NumPy 和 SciPy 邮件列表中的 David-Warde FarleyZachary Pincus 欢呼:)

=============

你好,

我有一张图像,其中包含由粒子光谱仪测量的冰粒子的阴影。我希望能够识别每个对象,以便以后可以在计算中进一步分类和使用它们。

本质上,我愿意做的是简单地实现一个模糊选择工具,我可以简单地选择每个实体。

我怎样才能轻松解决这个问题? (最好使用 Python)

谢谢。

注意:在我的问题中,我将每个特定的连接像素称为对象或实体。我打算提取它们并创建 NumPy 数组表示,如下所示。 (这里我使用左上角的对象;如果存在像素,则使用 1,如果不使用 0。该对象的形状是 3 x 3,对应的 3 像素高 x 3 像素宽。这些是真实冰粒子在 2D 域上的投影,假设它们是球形的,等效半径是(高度+宽度)/2,之后会进行一些缩放——从像素到实际大小和体积计算)

import numpy as np

np.array([[1,1,1], [1,1,1], [0,0,1]])

array([[1, 1, 1],
       [1, 1, 1],
       [0, 0, 1]])

这是我将要使用的图片中的一部​​分。

screenshot http://img43.imageshack.us/img43/2327/particles.png

【问题讨论】:

  • 简单的对象识别对我来说听起来很矛盾。
  • 你有什么替代建议?
  • 请不要在您的问题中说“已解决”。要么接受最佳答案,要么回答您自己的问题并接受。

标签: python image-processing computer-vision pattern-recognition


【解决方案1】:

查看您提供的图像,您接下来需要做的就是应用一个简单的region growing algorithm

如果我使用 MATLAB,我会使用 bwlabel/bwboundaries 函数。我相信在 Numpy 的某个地方有一个等效的函数,或者按照@kwatford 的建议将 OpenCV 与 python 包装器一起使用

【讨论】:

  • SciPy 包具有类似的标记功能 (docs.scipy.org/doc/scipy/reference/generated/…),我可以通过使用它正确标记所有像素。但这只能解决问题的第一部分。我应该能够分别区分每个实体。不幸的是,没有这个功能。需要写:)
  • 按照我的理解,图片中的每个蓝色物体都是一个实体,对吧?然后通过将所有像素标记为区域,您只需选择标记为一个的所有像素,然后选择标记为两个的像素,依此类推以获取每个对象...下一步是为每个对象提取一些特征(边界、形状、 area, size, ...),将用于监督分类任务。
  • 我在“注意”部分的问题中澄清了我对实体的使用。现在,我所要做的就是在某些情况下为每个对象获取边界矩形或正方形的宽度和高度。
  • 为了使这更加相似 [在 matlab 之外],所有 bw 命令都使用连通分量算法。
【解决方案2】:

我过去常常对显微照片进行这种分析,最终将我需要的一切都放入了一个用 C 语言编写并通过 Tcl 驱动的图像处理和分析包中。 (它只适用于 512 x 512 的图像,这解释了为什么 512 如此频繁地出现。分配了各种大小的像素的图像,但大部分工作都是用 8 位像素完成的,这解释了为什么会有这样的业务0xff 和图像上的最大有意义计数 254。)

简而言之,Tcl 命令开头的“zz”将行的其余部分发送到包的解析器,该解析器使用给定的参数调用适当的 C 例程。 'zz' 之后是一个参数,指示命令的输入和输出。 (可以有多个输入,但只有一个输出。)“r”表示 512 x 512 x 8 位图像。第三个词是要调用的命令的名称; 'graphs' 标记图像,如下文所述。所以,“zz rr graphs”的意思是“调用 ZZ 解析器;将 r 图像输入到 graphs 命令并取回 r 图像。 Tcl 命令行的其余部分指定使用哪个预分配的映像。 ('g' 图像是一个 ROI,即感兴趣区域的图像;几乎所有 ZZ 操作都是在 ROI 控制下完成的。)所以,'r1 r1 g8' 意味着'使用 r1 作为输入,使用 r1 作为输出(即标记输入图像本身),并在图像 g8 上的相应像素——即用作 ROI 的 r8 ——>0 处执行操作。

我不认为它在任何地方都可以在线获得,但如果你想通过源代码挑选甚至编译整个 shebang,我很乐意将它发送给你。这是手册的摘录(但我想我在这么晚的时候看到手册中有一些错误 --- 这很尴尬......):

示例 6. 计数特征。

问题

计数是一项常见的任务。计数的项目称为“特征”,通常需要仔细准备图像,使特征与要计数的真实对象一一对应。然而,在这里,我们忽略了图像准备,而是考虑了计数的机制。第一个计数练习是找出 ./cells 目录中的图像上有多少特征?

方法

首先,让我们定义“特征”。特征是最大的一组“集合”(非零)像素,所有这些像素都可以通过从一个集合像素沿着南北东西(上下左右)路线移动到另一个集合像素来到达,开始从给定的集合像素。在图像上检测和标记此类特征的 zz 命令是“zz rr graphs R:src R:dest G:ROI”,之所以这么称呼是因为此类特征的数学术语是“图形”。如果设置了图像上的所有像素,则图像上只有一个图形,但它包含 262144 个像素(512 * 512)。如果像素在棋盘图案中设置并清除(等于零), 那么将有 131072 (512 * 512 / 2) 个图,但每个图只包含一个像素。 简而言之,“zz rr 图”从图像的左上角开始扫描每个 从左到右连续一行,直到找到一个集合像素,然后找到所有通过北、南、东或西边界连接到该像素的集合像素(“4-connected”)。然后它将该图中的所有像素设置为 1 (0x01)。找到并标记图 1 后,它会在第一次发现图 1 之后的像素处再次开始扫描,这一次忽略任何已经属于图的像素。它找到的前 254 个图形将被唯一标记;但是,之后找到的所有图形都将标记为值 255 (0xff) 因此无法相互区分。能够准确统计任意数量的图的关键是对每张图像进行分阶段处理,即找出一张图像上的图的数量,如果数量大于254,则擦除刚刚找到的254张图,重复处理直到找到 254 个或更少的图。 Tcl 语言提供了设置此操作控制的方法。

让我们开始构建所需的命令,将 ZZ 图像文件读入 R 图像并检测和标记图形。在处理循环之前,我们声明一个变量并将其归零以保存图像系列中的特征总数。在处理循环中,我们首先将图像文件读入 R 图像并检测和标记图形。

zz ur to $inDir/$img r1
zz rr graphs r1 r1 g8

接下来,我们将一些变量归零以跟踪计数,然后使用“ra max”命令确定是否检测到超过 254 个图。

set nGraphs [ zz ra max r1 a1 g1 ]

如果 nGraphs 确实等于 255,则应将 254 个准确计数的图形添加到总数中,应删除从 1 到 254 的图形,并重复计数以减少以下图形的数量255.

while {$nGraphs == 255} {
  incr sumGraphs 254
  zz rbr lt r1 155 r1 g1 0 255 
  set sumGraphs 0
  zz rr graphs r1 r1 g8
  set nGraphs [ zz ra max r1 a1 g8 ]
}

当“while”循环退出时,变量nGraphs必须保存一个小于255的数字,即精确计数的图数;这被添加到图像系列中不断增加的特征总数中。

incr sumGraphs $nGraphs

在处理循环之后,打印出系列中找到的特征总数。

puts “Total number of features in $inDir \
images $beginImg through $endImg is $sumGraphs.”

在处理循环之后,打印出系列中找到的特征总数。

【讨论】:

  • 这是一个非常冗长的答案。理解你的解释需要一些时间:)
  • 请注意,我添加了第 2 段作为包的 Tcl 命令行语法的缩影介绍。这可能有助于你的“把握”。顺便说一句,手册中还有其他示例展示了如何使用形态学操作来准备图像,然后在找到并计算特征之后,执行诸如对它们进行尺寸分布之类的操作。我从来没有认真尝试过让它适应 Python,尽管有一段时间我一直在考虑这样做。
  • 另外顺便说一句:'graphs' 基本上使用 Paul Heckbert 的 Graphics Gems, Vol.I, p.721 中的算法。
  • 再次感谢您的冗长解释。我已经解决了这个问题,它可以满足我的需要。
【解决方案3】:

Connected component analysis 可能就是您要找的。​​p>

【讨论】:

  • 我知道这种技术肯定有新的 :) 感谢您的指点。 pygraph (code.google.com/p/python-graph) 和带有 Python 包装的 opencv 都对这些算法有一些支持,但是它们的用法对我来说不是很清楚。你用过这些功能吗?
【解决方案4】:
  1. 扫描每个方格(例如从左上角、从左到右、从上到下)

  2. 当你击中一个蓝色方块时:

    一个。将此方格记录为新对象的位置

    b.找到所有其他相邻的蓝色方块(例如,通过查看该方块的邻居以及这些邻居的邻居等)并将它们标记为同一对象的一部分

  3. 继续扫描

  4. 当您找到另一个蓝色方块时,请先测试它是否是已知对象的一部分,然后再进行第 2 步;或者,在步骤 2b 中,将任何正方形与对象关联后擦除它

【讨论】:

  • 我正在考虑实现与您在此处提到的类似的东西。感谢您比我清楚地布置:)
  • 在一些帮助下,我编写了一个简单的 flood_fill 实现,并且可以计算给定图像上对象(冰粒子阴影)的数量。而且,是的,它包括我预期的递归。现在我希望能够构造表示每个对象的简单 numpy 数组。 (正如我的问题中另外展示的那样)最后我正在考虑将所有这些数组附加到一个数组中,稍后我可以简单地循环并获取它们的形状。形状很重要,因为我会将它们用于冰粒对象的高度和宽度。
【解决方案5】:

OpenCV 有一个 Python 接口,您可能会觉得它很有用。

【讨论】:

猜你喜欢
  • 2013-12-15
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多