Skip to content Skip to sidebar Skip to footer

Draw Ellipse In Python Pil With Line Thickness

I am trying to draw a circle on an image, using Python. I tried this using PIL but I would like to specify a linewidth. Currently, PIL draws a circle but the border is too thin. He

Solution 1:

I had the same problem, and decided to write a helper function, similar to yours. This function draws two concentric ellipses in black and white on a mask layer, and the intended outline colour is stamped onto the original image through the mask. To get smoother results (antialias), the ellipses and mask is drawn in higher resolution.

Output with and without antialias

ellipses with PIL

The white ellipse is 20 pixels wide, and the black ellipse is 0.5 pixels wide.

Code

from PIL import Image, ImageDraw

defdraw_ellipse(image, bounds, width=1, outline='white', antialias=4):
    """Improved ellipse drawing function, based on PIL.ImageDraw."""# Use a single channel image (mode='L') as mask.# The size of the mask can be increased relative to the imput image# to get smoother looking results. 
    mask = Image.new(
        size=[int(dim * antialias) for dim in image.size],
        mode='L', color='black')
    draw = ImageDraw.Draw(mask)

    # draw outer shape in white (color) and inner shape in black (transparent)for offset, fill in (width/-2.0, 'white'), (width/2.0, 'black'):
        left, top = [(value + offset) * antialias for value in bounds[:2]]
        right, bottom = [(value - offset) * antialias for value in bounds[2:]]
        draw.ellipse([left, top, right, bottom], fill=fill)

    # downsample the mask using PIL.Image.LANCZOS # (a high-quality downsampling filter).
    mask = mask.resize(image.size, Image.LANCZOS)
    # paste outline color to input image through the mask
    image.paste(outline, mask=mask)

# green background image
image = Image.new(mode='RGB', size=(700, 300), color='green')

ellipse_box = [50, 50, 300, 250]

# draw a thick white ellipse and a thin black ellipse
draw_ellipse(image, ellipse_box, width=20)

# draw a thin black line, using higher antialias to preserve finer detail
draw_ellipse(image, ellipse_box, outline='black', width=.5, antialias=8)

# Lets try without antialiasing
ellipse_box[0] += 350 
ellipse_box[2] += 350 

draw_ellipse(image, ellipse_box, width=20, antialias=1)
draw_ellipse(image, ellipse_box, outline='black', width=1, antialias=1)

image.show()

I've only tested this code in python 3.4, but I think it should work with 2.7 without major modification.

Solution 2:

Simple (but not nice) solution is to draw two circles (the smaller one with color of background):

outline = 10# line thickness
draw.ellipse((x1-outline, y1-outline, x2+outline, y2+outline), fill=outline_color)
draw.ellipse((x1, y1, x2, y2), fill=background_color)

Solution 3:

I don't think there's a way to specify ellipse thickness, but you probably can draw lines at each pixel where ellipse pass, with the argument width=...

NB: I'm foreign, so sorry if my english is wrong.

Solution 4:

From version 5.3.0 onwards, released on 18 Oct 2018, Pillow has supported width for ImageDraw.ellipse. I doubt many people are using PIL nowadays.

Solution 5:

You can use the Image.core.draw method like this:

zero_array = np.zeros((224,224))
im = Image.fromarray(np.uint8(zero_array))
draw = ImageDraw.Draw(im)
dr_im = Image.core.draw(im.getdata(), 0)
dr_im.draw_rectangle((22,33, 150,100),220,2)
dr_im.draw_rectangle((22,33, 150,100),125,0)
#draw.rectangle((22,33, 150,100), fill=220,outline = 125)
print(np.array(im)[33][23])
im.show()

Post a Comment for "Draw Ellipse In Python Pil With Line Thickness"