python - 放置具有可变密度的点

标签 python algorithm radial-gradients

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

例如,这是一个二维高斯场,反转 s.t.质心值为 0,周长为 100:

Gaussian field

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

Point overlay

请注意径向向外展开的方式。

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

enter image description here

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

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

非常感谢任何帮助:)

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()

最佳答案

这是一个廉价而简单的方法,尽管它需要手动设置一个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

关于python - 放置具有可变密度的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49282945/

相关文章:

python - 在tensorflow的seq2seq函数中使用预先训练的词嵌入

python - 优化所有可能组合的效率

php - PHP中的加解密算法

Simon Plouffe 1996 计算 pi 算法的 C 实现失败

css - 如何改变 CSS 中径向渐变的曲线?

python - 文本文件前面的字节

Python装饰器自动定义__init__变量

algorithm - 哪种算法可以根据历史对列表进行排名

CSS3 径向渐变语法解释

html - CSS:带有渐变的背景图像 "overlay"