像素和几何形状 - Python / PIL

时间:2011-02-16 13:18:54

标签: python math python-imaging-library

我正在尝试基于点构建基本热图。每个点都有一个热半径,因此用圆圈表示。

问题是需要根据与圆心的距离将颜色转换为像素列表。

很难找到针对很多方面的最佳解决方案,我现在所拥有的与此类似:

for pixels in pixels:
    if (pixel.x - circle.x)**2 + (pixel.y - circle.y)**2 <= circle.radius:
        pixel.set_color(circle.color)

编辑:

我的数据:

  • 圆圈中心的像素
  • 圆半径(整数)

任何提示?

4 个答案:

答案 0 :(得分:3)

不是逐像素地进行,而是使用具有抗锯齿功能的更高级别界面,例如the aggdraw module及其ellipse(xy, pen, brush)功能。

循环所需的颜色步数(例如,半径/ 2),并使用255 / number_of_steps * current_step作为填充颜色的alpha值。

答案 1 :(得分:1)

对于绘图,通常建议使用matplotlib库(例如使用imshow进行热图)。当然matplotlib也支持color gradients

但是,我真的不明白你想要完成什么。如果您只想绘制一堆彩色圆圈,那么几乎任何图形库都可以(例如在PIL中使用ellipse函数)。

听起来你想根据它们与中心的距离为像素着色,但你自己的示例代码表明颜色是不变的?

答案 2 :(得分:1)

如果你自己处理像素而你的目的是提高表现,你可以只关注方格[x - radius; x + radius] * [y - radius; y + radius],因为圆圈的点位于此处。这将为您节省大量无用的迭代,如果您当然可以关注这个区域(即您的像素不仅仅是没有每行和每列索引的数组)。

您甚至可以确保方形[x - radius*sqrt(2)/2; x + radius*sqrt(2)/2] * [y - radius*sqrt(2)/2; y + radius*sqrt(2)/2]中的像素必须使用基本三角法(圆圈内的最大方块)进行着色。

所以你可以这样做:

import math
half_sqrt = math.sqrt(2) / 2
x_max = x + half_sqrt
y_max = y + half_sqrt
for (i in range(x, x + radius + 1):
    for (j in range(y, y + radius + 1):
        if (x <= x_max and y <= y_max):
            colorize_4_parts(i, j)
        else:
            pixel = get_pixel(i, j)
            if (pixel.x - circle.x)**2 + (pixel.y - circle.y)**2 <= circle.radius:
                # Apply same colors as above, could be a function
                colorize_4_parts(i, j)

def colorize_4_parts(i, j):
    # Hoping you have access to such a function get_pixel !
    pixel_top_right = get_pixel(i, j)
    pixel_top_right.set_color(circle.color)
    pixel_top_left = get_pixel(2 * x - i, j)
    pixel_top_leftt.set_color(circle.color)
    pixel_bot_right = get_pixel(i, 2 * y - j)
    pixel_bot_right.set_color(circle.color)
    pixel_bot_left = get_pixel(2 * x - i,  2 * y - j)
    pixel_bot_leftt.set_color(circle.color)

这是经过优化的,可以将昂贵的计算工作降至最低。

编辑:功能更新再次更高效:我忘记了我们有水平和垂直的双重对称,所以我们只能计算右上角!

答案 3 :(得分:0)

这是一项非常常见的操作,以及人们如何做到这一点......

摘要:代表网格上的点密度,如果需要,使用 2D卷积平滑此值(这会将您的点指向圆圈),并将其绘制为< strong>使用matplotlib的热图。

更详细:首先,为热图制作一个2D网格,然后将数据点添加到网格中,当数据点落入单元格时,单元格递增1。其次,制作另一个网格来表示你想要给每个点的形状(通常人们使用圆柱或高斯或类似的东西)。第三,使用scipy.signal.convolve2d,将这两者合在一起。最后,使用matplotlib的imshow函数绘制卷积图,这将是你的热图。

如果您不能使用标准方法中建议的工具,那么您可能会找到解决方法,但它有优势。例如,卷积将很好地处理圆圈重叠的情况。