使用PIL的Imagedraw创建给定厚度的弧形

9
我正在尝试使用PIL和Imagedraw创建分段弧形。 arc函数使我可以轻松绘制一条弧线,但它只是一条线。 我需要能够放置给定半径和厚度(从内径到外径)的弧形,但是我无法找到任何类型的厚度或宽度设置。 有没有办法做到这一点? 如果没有,是否有其他方法可以使用PIL完成此操作?
代码片段:
import Image
import ImageDraw

conv = 0.1
ID = 15
OD = 20
image = Image.new('1',(int(ceil(OD/conv))+2,int(ceil(OD/conv))+1), 1)
draw = ImageDraw.Draw(image)
diam = OD-ID
box=(1, 1, int(ceil(diam/conv)), int(ceil(diam/conv))) #create bounding box
draw.arc(box, 0, 90, 0) #draw circle in black
4个回答

3
我根据Mark的建议创建了以下基于弧度替换的函数:

https://gist.github.com/skion/9259926

也许不是像素完美(也不快),但对于我需要的来说似乎已经很接近了。如果你有更好的版本,请在Gist中评论。
def arc(draw, bbox, start, end, fill, width=1, segments=100):
    """
    Hack that looks similar to PIL's draw.arc(), but can specify a line width.
    """
    # radians
    start *= math.pi / 180
    end *= math.pi / 180

    # angle step
    da = (end - start) / segments

    # shift end points with half a segment angle
    start -= da / 2
    end -= da / 2

    # ellips radii
    rx = (bbox[2] - bbox[0]) / 2
    ry = (bbox[3] - bbox[1]) / 2

    # box centre
    cx = bbox[0] + rx
    cy = bbox[1] + ry

    # segment length
    l = (rx+ry) * da / 2.0

    for i in range(segments):

        # angle centre
        a = start + (i+0.5) * da

        # x,y centre
        x = cx + math.cos(a) * rx
        y = cy + math.sin(a) * ry

        # derivatives
        dx = -math.sin(a) * rx / (rx+ry)
        dy = math.cos(a) * ry / (rx+ry)

        draw.line([(x-dx*l,y-dy*l), (x+dx*l, y+dy*l)], fill=fill, width=width)

好的,谢谢!有一个小问题:Draw.arc()接受270, 0作为参数来绘制从12点到3点的弧形。上面的代码只能使用270, 360 - Jens

1

PIL无法绘制宽弧,但Aggdraw可以,并且与PIL(同一作者)配合良好。


我设计了一个复杂的嵌套方案,通过绘制具有像素厚度半径变化的弧线来获得粗线条,但结果在末端太过于不平滑,因为imagedraw只接受角度的整数值。 - Elliot

0

使用直线段模拟弧,并将这些段的坐标放入列表中。使用draw.linewidth选项绘制弧。


0
我发现的一个技巧是在黑色圆内部画一个白色圆。您可以使用pieslice方法根据需要将其分解。渲染是顺序的,因此您只需正确排序即可。困难的部分是确保定位正确,由于Imagedraw使用边界框而不是中心和半径坐标。您必须确保所有内容的中心最终完全重合。

此解决方案仅在有限情况下有效,请参见评论。


是的,这是一种作弊的方法。如果弧线内部已经有任何绘制的内容,它就不起作用了。 - Mark Ransom
没关系,如果你想要不断扩大的间隔,这很好。但如果你想要固定弧长缺失,这并不能解决问题。 - Elliot
你可以使用行命令,如果你非常小心地偏移。 - Elliot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接