2013-03-15 43 views
2

语境在numpy的阵列取决于圆

我需要测量在python结合的圆的区域的面积改变的值。我想出了使用numpy数组的方式。首先,我用零填充一个网格(numpy数组),网格中的每个位置对应的长度为0.5cm。然后我将圆的中心放到网格上,并在网格中将此值更改为1。我知道圆的半径,所以我可以计算圆的面积,因为我知道圆的面积,我改变了圆的区域中的网格中的零点。然后我计算网格中的频率,并用它来计算组合圆的面积,因为我知道网格中每个位置的长度,我可以计算出面积。目前这是一种非常粗糙的谷物方法,我计划一旦确定了算法,就将其更改为更精细的谷物。

如果你看我贴下面的图片,描述我的想法更好。我的网格上有两个圆圈(红线),圆圈的中心标有蓝色方块,圆圈占据的区域是浅橙色。我想改变与橙色标记的区域。我现在可以将橙色的方块水平和垂直地改变为圆心,但是从中心对角线的方格会给我带来麻烦。

enter image description here

当前代码

class area(): 

    def make_grid(self): 
     ''' 
     Each square in the grid represents 0.5 cm 
     ''' 
     import numpy as np 
     grid = np.zeros((10,10)) 
     square_length = 0.5 
     circles = {'c1':[[4,2],1.5],'c2':[[5,6],2.0]} 

     print grid 
     for key,val in circles.iteritems(): 
      grid[val[0][0]][val[0][1]] = 1 
      area = int((val[1] - square_length)/0.5)    
      for i in xrange(1,area+1): 
       grid[val[0][0]][val[0][1]+i] = 1 # Change column vals in +ve direction 
       grid[val[0][0]][val[0][1]-i] = 1 # Chnage column vals in -ve direction 
       grid[val[0][0]+i][val[0][1]] = 1 # Chnage row vals in +ve direction 
       grid[val[0][0]-i][val[0][1]] = 1 # Chnage row vals in -ve direction 

     print '' 
     print grid 

在上述词典中,关键是圆名称,在值的第一个元素是圆心坐标和所述第二元件是圆的半径。

代码输出:

[[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] 
[ 0. 0. 1. 0. 0. 0. 1. 0. 0. 0.] 
[ 0. 0. 1. 0. 0. 0. 1. 0. 0. 0.] 
[ 1. 1. 1. 1. 1. 0. 1. 0. 0. 0.] 
[ 0. 0. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 0. 0. 1. 0. 0. 0. 1. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] 
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]] 
+1

你不是应该改为通过满格步进的面积,计算出到每个圆心为每个网格的距离点,然后看看它是否在圈内并且将网格点计数器加1?这样,有些点将会有2个而不是1个,但是至少圆中的所有点(舍入问题除外)都将被计数。这是慢的,因为你必须通过所有的点,但它可能更直接。 – Evert 2013-03-15 12:27:38

+1

你认为几何解决方案“测量面积”? http://mathworld.wolfram.com/Circle-CircleIntersection.html – MBo 2013-03-15 12:35:32

+1

我已经考虑过一个几何解决方案,但是如果我有多个圆圈,并且在这个问题中描述了'缺少区域',就会出现问题:http://stackoverflow.com/questions/1667310 /合并区域的重叠圆圈 – Harpal 2013-03-15 12:38:14

回答

2

根据@Jaime的评论更新。

我可能会从这样的事情开始。要点是正确计算圆内的像素。

import numpy as np 
import matplotlib.pyplot as plt 

grid = np.zeros((10,10), dtype=np.bool) 
square_length = 0.5 
circles = {'c1':[[4,2],1.5],'c2':[[5,6],2.0]} 

# Generate arrays of indices/coordiates so we can do the 
# calculations the Numpy way, without resorting to loops 
# I always get the index order wrong so double check... 
xx = np.arange(grid.shape[0]) 
yy = np.arange(grid.shape[1]) 

for val in circles.itervalues(): 
    radius = val[1] 
    # same index caveat here 
    # Calling Mr Pythagoras: Find the pixels that lie inside this circle 
    inside = (xx[:,None] - val[0][0]) ** 2 + (yy[None, :] - val[0][1]) ** 2 <= (radius ** 2) 
    # do grid & inside and initialize grid with ones for intersection instead of union 
    grid = grid | inside 

plt.imshow(grid) 
plt.show() 

如果你是个路口之后,请注意您的圆心是sqrt(17) ~= 4.123..单位分开,两个半径的总和来3.5所以实际上不存在重叠。

+1

+1我认为这是要走的路。我将摆脱'np.sqrt'并与'radius ** 2'比较。另外,通过使用'&',我认为你正在确定**所有**圈子重叠的点。使用'zeros'和'|'的网格来取代**任意**圆圈内的点。你也可以不使用'meshgrid',而是使用'xx = np.arange(grid.shape [0])'和'yy = np.arange(grid.shape [1])',然后使用广播作为'inside =(xx [:, None] --val [0] [0])** 2 +(yy -val [0] [1])** 2 <=半径** 2'以减少耗尽内存的实现。 – Jaime 2013-03-15 14:33:15

+0

啊,是的,我理解“组合圈子”是指交叉点,但它是有道理的有联合。感谢您的评论 - 将更新我的答案。 – YXD 2013-03-15 15:27:11

1

您只搜索直接右键,然后从中间偏左。为了从中心获得正方形对角线,您可能必须使用Pythagorean theorem。利用这个定理,您可以通过相对于圆心作为边长在水平和垂直方向上使用偏移量来找到正方形的斜边。然后可以将斜边与半径进行比较,如果斜边是两者中较短的一个,则将平方值增加一。

另外半径的使用有点奇怪,因为它没有使用广场中间的中心。这使得半径为2的圆的直径为3.5。

0

可以使用Floodfill algorithm与停止条件稍微修改:兼顾颜色和距离圆心

附:用于小尺寸区域的哈克方法:绘制实心圆和计数颜色像素...

1

您可以使用蒙特卡罗方法找到重叠区域的面积。这样会更准确。 http://www.chem.unl.edu/zeng/joy/mclab/mcintro.html

找到正方形的边界,然后用随机数填充,并为每个随机数检查随机数是否在圆内。

if (np.sqrt((xx - val[0][0]) ** 2 + (yy - val[0][1]) ** 2) <= radius) :inside=inside+1 

面积=总无内部产生像素的圆/总像素数*平方