在 Python PIL 中用线条粗细绘制椭圆
Draw Ellipse in Python PIL with line thickness
我正在尝试使用 Python 在图像上画一个圆圈。我使用 PIL 进行了尝试,但我想指定一个 linewidth
。目前PIL画了一个圆但是边框太细
这是我所做的。
对于测试图像:我在 MS Paint 中创建了一个 1632 X 1200 图像并将其填充为绿色。我称它为test_1.jpg。这是输入文件:
from PIL import Image, ImageDraw
im = Image.open('test_1.jpg')
width, height = im.size
eX, eY = 816,816 #Size of Bounding Box for ellipse
bbox = (width/2 - eX/2, height/2 - eY/2, width/2 + eX/2, height/2 + eY/2)
draw = ImageDraw.Draw(im)
bbox_L = []
for j in range(0,5):
bbox_L.append([element+j for element in bbox])
draw.ellipse(tuple(bbox_L[j]), outline ='white')
im.show()
基本上,我尝试绘制多个以同一点为中心但半径不同的圆。我的想法是,这会产生更粗线的效果。
但是,这会产生下面附件中显示的输出:
问题:如您所见,左下角和右上角太细了。此外,各个圆圈之间存在间隙(见左上和右下)。
圆的粗细不一。我看的是一个厚度均匀的圆
问题:
有没有一种方法可以使用 PIL、NumPy 等在 Python 中在像 test_1.jpg 这样的图像上画一个圆圈,然后 指定线宽?
我不认为有指定椭圆粗细的方法,但您可能可以在椭圆通过的每个像素处绘制线条,参数 width=...
注意:我是外国人,如果我的英语有误,请见谅。
简单(但不是很好)的解决方案是绘制两个圆圈(较小的圆圈带有背景颜色):
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)
我遇到了同样的问题,因此决定编写一个类似于您的辅助函数。该函数在遮罩层上绘制黑白两个同心椭圆,将想要的轮廓颜色通过遮罩印在原图上。为了获得更平滑的结果(抗锯齿),椭圆和蒙版以更高分辨率绘制。
带和不带抗锯齿的输出
白色椭圆宽 20 像素,黑色椭圆宽 0.5 像素。
代码
from PIL import Image, ImageDraw
def draw_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()
我只在 python 3.4 中测试过此代码,但我认为它应该适用于 2.7 而无需进行重大修改。
您可以像这样使用Image.core.draw
方法:
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()
来自版本 5.3.0 onwards, released on 18 Oct 2018, Pillow has supported width
for ImageDraw.ellipse
。我怀疑现在很多人都在使用 PIL。
我正在尝试使用 Python 在图像上画一个圆圈。我使用 PIL 进行了尝试,但我想指定一个 linewidth
。目前PIL画了一个圆但是边框太细
这是我所做的。
对于测试图像:我在 MS Paint 中创建了一个 1632 X 1200 图像并将其填充为绿色。我称它为test_1.jpg。这是输入文件:
from PIL import Image, ImageDraw
im = Image.open('test_1.jpg')
width, height = im.size
eX, eY = 816,816 #Size of Bounding Box for ellipse
bbox = (width/2 - eX/2, height/2 - eY/2, width/2 + eX/2, height/2 + eY/2)
draw = ImageDraw.Draw(im)
bbox_L = []
for j in range(0,5):
bbox_L.append([element+j for element in bbox])
draw.ellipse(tuple(bbox_L[j]), outline ='white')
im.show()
基本上,我尝试绘制多个以同一点为中心但半径不同的圆。我的想法是,这会产生更粗线的效果。
但是,这会产生下面附件中显示的输出:
问题:如您所见,左下角和右上角太细了。此外,各个圆圈之间存在间隙(见左上和右下)。
圆的粗细不一。我看的是一个厚度均匀的圆
问题: 有没有一种方法可以使用 PIL、NumPy 等在 Python 中在像 test_1.jpg 这样的图像上画一个圆圈,然后 指定线宽?
我不认为有指定椭圆粗细的方法,但您可能可以在椭圆通过的每个像素处绘制线条,参数 width=...
注意:我是外国人,如果我的英语有误,请见谅。
简单(但不是很好)的解决方案是绘制两个圆圈(较小的圆圈带有背景颜色):
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)
我遇到了同样的问题,因此决定编写一个类似于您的辅助函数。该函数在遮罩层上绘制黑白两个同心椭圆,将想要的轮廓颜色通过遮罩印在原图上。为了获得更平滑的结果(抗锯齿),椭圆和蒙版以更高分辨率绘制。
带和不带抗锯齿的输出
白色椭圆宽 20 像素,黑色椭圆宽 0.5 像素。
代码
from PIL import Image, ImageDraw
def draw_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()
我只在 python 3.4 中测试过此代码,但我认为它应该适用于 2.7 而无需进行重大修改。
您可以像这样使用Image.core.draw
方法:
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()
来自版本 5.3.0 onwards, released on 18 Oct 2018, Pillow has supported width
for ImageDraw.ellipse
。我怀疑现在很多人都在使用 PIL。