2D列表中的聚类上的边界框 [英] Bounding box on clusters in a 2D list

查看:49
本文介绍了2D列表中的聚类上的边界框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有


ex:x = [[1,1,1,0,0,0,0,0,0,0,0,1,1, 1,1,0,0,0],

[1,1,1,0,1,1,0,0,0,0,0,1,1,1,1, 0,0,0],

[1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0, 0],

[0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0]]

我想要的是一个边界框,我们在这个区域找到了

1'的集群。所以例如在上面的列表中,前3个roes和colums有1'' s

所以那个盒子的面积是3x3

所以我的最后一个阵列应该有一个大约的区域阵列

1''像

area = [9,4 ....]

希望我对我的问题很清楚。

解决方案

我希望这就是你所需要的,有时候理解这个问题是

其中一个最难的部分:-)


如果你可以使用图形数据结构,你可以创建一个图形,然后

你可以找到所有连接组件的长度(缩进

减少到2个空间s):


.. def mat2graph(g,m,good =无,w = 1):

.."功能文档...

.. g.clear()

..如果m和isinstance(m,(list,tuple)):

。如果好的话!=无:

.. m = [行中e的好(e)]行中的m]

.. maxy = len(m )-1

.. maxx = len(m [0]) - 1

.. add = g.addBiArc

.. for y,枚举(m)行:

..对于x,e在枚举(行)中:

..如果e:

.. g.addNode((x,y))#对于孤立节点是必需的。

..如果x> 0且m [y] [x-1]:add((x,y) ,(x-1,y),w = w)

..如果x< maxx和m [y] [x + 1]:add((x,y),(x + 1) ,y),w = w)

..如果y> 0且m [y-1] [x]:add((x,y),(x,y-1),w = w)

..如果y< maxy和m [y + 1] [x]:add((x,y),(x,y + 1),w = w)

..

..来自图形导入图

.. g =图形()

.. m = [ [1,1,1,0,0,0 ,0,0,0,0,0,1,1,1,1,0,0,0],

.. [1,1,1,0,1,1,0 ,0,0,0,0,1,1,1,1,0,0,0],

.. [1,1,1,0,1,1,1,0 ,1,1,0,1,1,1,0,0,0,0],

.. [0,0,0,0,0,0,0,0,1 ,1,0,0,0,0,0,0,0,0]]

.. mat2graph(g,m)

..打印地图(len ,g.connectedComponents())

类似于mat2graph的东西可能会成为Graph的一种方法。

一个非常类似的程序可以用于其他python图形图书馆。


如果你不能使用图形数据结构,如果你需要更快,

你可以使用针对这个问题调整的泛洪填充算法:

.. def connected(m,foreground = 1,background = 0):

.. def floodFill4(m,r,c,newCol,oldCol):

.."""最简单的4连接泛洪填充算法,有很多

..更快的非递归填充算法。我修改了这个:

.. http://www.student.kuleuven.ac.be/~m0216922/CG/floodfill.html"""

..如果c> = 0且c< maxc和r> = 0且r< maxr和m [r] [c] == oldCol:

.. m [r] [ c] = newCol

.. floodFill4(m,r + 1,c,newCol,oldCol)

.. floodFill4(m,r-1,c,newCol, oldCol)

.. floodFill4(m,r,c + 1,newCol,oldCol)

.. floodFill4(m,r,c-1,newCol,oldCol)

..

.. maxr = len(m)

.. maxc = len(m [0])

.. newCol = 2

.. oldCol =前景

..对于x inrange(maxr):

.. for c in xrange(maxc):

..如果m [r] [c] == oldCol:

.. floodFill4(m,r,c,newCol = newCol ,oldCol = oldCol)

.. newCol + = 1

..#Frequences,这可以成为标准的python命令

.. freq = {}

..对于m中的行:

..对于e排:

..如果e in freq:

.. freq [e] + = 1

.. else:

.. freq [e] = 1

.. del freq [背景]

..返回freq.values()

..

.. m = [[1,1,1,0,0,0,0,0,0,0,0,1,1,1,1, 0,0,0],

.. [1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,0, 0,0],

.. [1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0, 0],

.. [0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0] ]

..打印连接(m)

有更快的方法来进行洪水填充:
http://www.codeproject.com/gdi/QuickFill.asp

我认为Python PIL并不支持洪水填充,我认为使用Numarray这样做是很慢的,并且它只对减少使用的

内存非常有用。 />
这个连接的程序很慢且很原始,并且它使用递归很多,

所以它可能会崩溃译码。您可以使用数据结构来自行实现堆栈,以加快此程序的运行速度。但是对于小的

矩阵我觉得这个连接就足够了^ _ ^


熊抱抱,

Bearophile


2005年4月23日13:17:55 -0700,su ******* @ gmail.com <苏******* @ gmail.com>写道:

如果我有

ex:x = [[1,1,1,0,0,0,0,0,0,0 ,0,1,1,1,1,0,0,0],
[1,1,1,0,1,1,0,0,0,0,0,1,1,1 ,1,0,0,0],
[1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,0 ],
[0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0]]
我是什么想要的是一个边界框,我们在这个区域找到了1个的簇。所以例如在上面的列表中,前3个roes和colums有1个'
所以那个盒子的面积是3x3
所以我的最后一个数组应该有一个大约区域的数组
1'就像
area = [9,4 ....]
4来自?

希望我对我的问题很清楚。



不清楚是否群集必须是矩形并填充他们的边界框

或是否


[[0,0,0,0,0],

+ ----- +

[0,| 1,1,| 0,0],

| |

[0,| 0,1,| 0,0],

+ ----- +

[0,0 ,0,0,0]]


是一个有三个1'的集群。或者实际上是否是边界框。必须是矩形的。

即,对角线簇怎么样?

,__,

[[0,0,| 1,| 0 ,0],

_ / _ /,__,

[0,/ 1,/ 0,0,| 1],

_ / _ / _ / /

[1,/ 0,0,/ 1,/ 0],

_ / /

[ 0,0,/ 1,/ 0,0]]


或者应该是

+ ------------ - +

[[| 0,0,1,0,0 |],

| |

[| 0,1,0,0,1 |],

| |

[| 1,0,0,1,0 |],

| |

[| 0,0,1,0,0 |]]

+ ------------- +


因为长度为3对角线的两个3x3正方形会重叠。


问候,

Bengt Richter


里希特,是的,我正在寻找的是具有矩形

边界框的集群,如第一个图所示。


If I have

ex: x = [[1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0],
[1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0],
[1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,0],
[0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0]]
what I want is a boundingbox over the region where we find clusters of
1''s.So for instance in the above list first 3 roes and colums have 1''s
so the area of that box is 3x3
so my final array should have an array of approx areas of clusters of
1''s like
area = [ 9,4 ....]
Hope I am clear with my question.

解决方案

I hope this is what you need, sometimes understanding the question is
one of the hardest parts :-)

If you can use a graph data structure, you can create a graph, and then
you can find the lenght of all its connected components (indentations
reduced to 2 spaces):

.. def mat2graph(g, m, good=None, w=1):
.. "Function docs..."
.. g.clear()
.. if m and isinstance(m, (list, tuple)):
.. if good != None:
.. m = [[good(e) for e in row] for row in m]
.. maxy = len(m)-1
.. maxx = len(m[0])-1
.. add = g.addBiArc
.. for y, row in enumerate(m):
.. for x, e in enumerate(row):
.. if e:
.. g.addNode((x,y)) # Necessary for isolated nodes.
.. if x>0 and m[y][x-1]: add( (x,y), (x-1,y), w=w)
.. if x<maxx and m[y][x+1]: add( (x,y), (x+1,y), w=w)
.. if y>0 and m[y-1][x]: add( (x,y), (x,y-1), w=w)
.. if y<maxy and m[y+1][x]: add( (x,y), (x,y+1), w=w)
..
.. from graph import Graph
.. g = Graph()
.. m = [[1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0],
.. [1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0],
.. [1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,0],
.. [0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0]]
.. mat2graph(g, m)
.. print map(len, g.connectedComponents())

Something similar to mat2graph will probably become a method of Graph.
A quite similar program can be used for other python graph libraries.

If you cannot use a graph data structure, of if you need to go faster,
you can use a flood fill algorithm tuned for this problem:
.. def connected(m, foreground=1, background=0):
.. def floodFill4(m, r,c, newCol, oldCol):
.. """Simplest 4-connected flood fill algorithm, there are much
.. faster non-recursive ones. I''ve modified this from:
.. http://www.student.kuleuven.ac.be/~m0216922/CG/floodfill.html"""
.. if c>=0 and c<maxc and r>=0 and r<maxr and m[r][c]==oldCol:
.. m[r][c] = newCol
.. floodFill4(m, r+1, c, newCol, oldCol)
.. floodFill4(m, r-1, c, newCol, oldCol)
.. floodFill4(m, r, c+1, newCol, oldCol)
.. floodFill4(m, r, c-1, newCol, oldCol)
..
.. maxr = len(m)
.. maxc = len(m[0])
.. newCol = 2
.. oldCol = foreground
.. for r in xrange(maxr):
.. for c in xrange(maxc):
.. if m[r][c] == oldCol:
.. floodFill4(m, r,c, newCol=newCol, oldCol=oldCol)
.. newCol += 1
.. # Frequences, this can be become a standard python command
.. freq = {}
.. for row in m:
.. for e in row:
.. if e in freq:
.. freq[e] += 1
.. else:
.. freq[e] = 1
.. del freq[background]
.. return freq.values()
..
.. m = [[1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0],
.. [1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0],
.. [1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,0],
.. [0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0]]
.. print connected(m)
There are much faster ways to do flood fills:
http://www.codeproject.com/gdi/QuickFill.asp
I think Python PIL doesn''t support flood fills, and I think doing it
with Numarray is slower, and it''s useful only to reduce the used
memory.
This connected program is slow and raw, and it uses recursivity a lot,
so it can crash the interpreter. You can use a data structure to
implement the stack yourself, to speed this program up. But for small
matrices I think this connected is enough ^_^

Bear hugs,
Bearophile


On 23 Apr 2005 13:17:55 -0700, "su*******@gmail.com" <su*******@gmail.com> wrote:

If I have

ex: x = [[1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0],
[1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0],
[1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,0],
[0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0]]
what I want is a boundingbox over the region where we find clusters of
1''s.So for instance in the above list first 3 roes and colums have 1''s
so the area of that box is 3x3
so my final array should have an array of approx areas of clusters of
1''s like
area = [ 9,4 ....] Where does the 4 come from?
Hope I am clear with my question.


Not quite clear on if "clusters" have to be rectangular and fill their bounding boxes
or whether

[[0, 0, 0, 0, 0],
+-----+
[0,|1, 1,|0, 0],
| |
[0,|0, 1,|0, 0],
+-----+
[0, 0, 0, 0, 0]]

is a cluster with three 1''s. Or indeed whether "bounding boxes" have to be rectangular.
I.e., what about diagonal clusters?
,__,
[[0, 0,|1,|0, 0],
_/ _/ ,__,
[0,/1,/0, 0,|1],
_/ _/ _/ /
[1,/0, 0,/1,/0],
_/ /
[0, 0,/1,/0, 0]]

Or should that be
+-------------+
[[|0, 0, 1, 0, 0|],
| |
[|0, 1, 0, 0, 1|],
| |
[|1, 0, 0, 1, 0|],
| |
[|0, 0, 1, 0, 0|]]
+-------------+

since two 3x3 squares around the length-3 diagonals would overlap.

Regards,
Bengt Richter


Richter,yes what I am looking for is for cluster with rectangular
bounding boxes as you explained in the first figure.


这篇关于2D列表中的聚类上的边界框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆