放置密度可变的点

时间:2018-03-14 16:24:31

标签: python algorithm radial-gradients

假设您有一个NxM矩阵,其值范围为[0,100]。我想做的是相对于该区域的值放置密度(反向)的点。

例如,这是一个2D高斯场,倒置的s.t.质心的值为0,周长为100:

Gaussian field

我想打包这些点,使它们看起来有点类似于这张图片:

Point overlay

注意向外的径向扩散。

我的尝试看起来有点不同:( ...

enter image description here

我尝试做的是(i)生成一个具有相同形状和大小的布尔区域,以及(ii)在行和列中移动。如果某个点的布尔数组的值是True,那么传递;否则,将[row,col]点添加到列表中,并使用True覆盖布尔数组,其半径与高斯数组中的值成比例。

对于这个例子,高斯选择并不重要,基本思想是:给定浮点矩阵,如何用一个与这些值成比例的密度来放置点?

非常感谢任何帮助:)

import matplotlib.pyplot as plt
import numpy as np
from math import exp

def gaussian(x,y,x0,y0,A=10.0,sigma_x=10.0,sigma_y=10.0):
    return A - A*exp(-((x-x0)**2/(2*sigma_x**2) + (y-y0)**2/(2*sigma_y**2)))

def generate_grid(width=100,height=100):
    grid = np.empty((width,height))
    for x in range(0,width):
        for y in range(0,height):
            grid[x][y] = gaussian(x,y,width/2,height/2,A=100.0)
    return grid

def cover_array(a,row,col,radius):
    nRows = np.shape(grid)[0]
    nCols = np.shape(grid)[1]
    mid = round(radius / 2)
    half_radius = int(round(radius))
    for x in range(-half_radius,half_radius):
        for y in range(-half_radius,half_radius):
            if row+x >= 0 and x+row < nRows and col+y >= 0 and y+col < nCols:
                if (x-mid)**2 + (y-mid)**2 <= radius**2:
                    a[row+x][col+y] = True


def pack_points(grid):
    points = []
    nRows = np.shape(grid)[0]
    nCols = np.shape(grid)[1]
    maxDist = 50.0
    minDist = 0.0
    maxEdge = 10.0
    minEdge = 5.0
    grid_min = 0.0
    grid_max = 100.0

    row = 0
    col = 0

    arrayCovered = np.zeros((nRows,nCols))

    while True:
        if row >= nRows:
            return np.array(points)

        if arrayCovered[row][col] == False:
            radius = maxEdge * ((grid[row][col] - grid_min) / (grid_max - grid_min))
            cover_array(arrayCovered,row,col,radius)
            points.append([row,col])

        col += 1
        if col >= nCols:
            row += 1
            col = 0

grid = generate_grid()
plt.imshow(grid)
plt.show()

points = pack_points(grid)

plt.scatter(points[:,0],points[:,1])
plt.show()

1 个答案:

答案 0 :(得分:2)

这是一种便宜而简单的方法,虽然它需要手动设置amount参数:

import numpy as np
import matplotlib.pyplot as plt

def gaussian(x,y,x0,y0,A=10.0,sigma_x=10.0,sigma_y=10.0):
    return A - A*np.exp(-((x-x0)**2/(2*sigma_x**2) + (y-y0)**2/(2*sigma_y**2)))

def distribute_points(data, amount=1):
    p = amount * (1 / data)
    r = np.random.random(p.shape)
    return np.where(p > r)

ii, jj = np.mgrid[-10:10:.1, -10:10:.1]
data = gaussian(ii, jj, 0, 0)
px, py = distribute_points(data, amount=.03)

plt.imshow(data)
plt.scatter(px, py, marker='.', c='#ff000080')
plt.xticks([])
plt.yticks([])
plt.xlim([0, len(ii)])
plt.ylim([0, len(jj)])

结果:

Points