根据圆的面积改变numpy数组中的值
背景
我需要在Python中测量多个圆的面积。我想出了一个方法,使用numpy数组。首先,我用零填充一个网格(numpy数组),网格中的每个位置代表0.5厘米的长度。然后,我把圆的中心放到网格上,并把这个位置的值改为1。因为我知道圆的半径,所以可以计算出圆的面积。知道了圆的面积后,我就可以把网格中落在圆面积内的零改为一。接着,我统计网格中一的数量,利用这个数量来计算所有圆的总面积。因为我知道网格中每个位置的长度,所以可以算出面积。目前这个方法比较粗糙,我打算在算法稳定后,改成更精细的方法。
示例
如果你看一下我下面发的图片,会更好地理解我的想法。网格上有两个圆(红线),圆的中心用蓝色方块标记,圆占据的区域是浅橙色的。我想把标记为橙色的区域改为一。目前我可以把橙色方块的水平和垂直方向上的位置改为一,但从中心到对角线的方块让我有些困扰。
当前代码
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.]]
4 个回答
你可以用蒙特卡罗方法来找出重叠区域的面积。这样做会更准确。
首先,确定这个正方形的边界,然后用随机数填充这个正方形。接着,对于每一个随机数,检查它是否在圆里面。
if (np.sqrt((xx - val[0][0]) ** 2 + (yy - val[0][1]) ** 2) <= radius) :inside=inside+1
面积=在圆内的像素总数/生成的像素总数*正方形的面积
你现在只是在中心的左右两边进行搜索。如果想要找到中心对角线上的方块,可能需要用到勾股定理。通过这个定理,你可以用中心点的水平和垂直偏移量来计算方块的斜边长度。然后,你可以把这个斜边长度和半径进行比较,如果斜边长度更短,就把方块的值加一。
另外,使用半径的方式有点奇怪,因为它并没有把方块的中心作为参考点。这就导致一个半径为2的圆,其直径变成了3.5。
根据@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
,所以实际上是没有重叠的。