Python
Как нарисовать круг в Python PIL: Pillow, ImageDraw и координаты
Чтобы нарисовать круг в Python через PIL, установите библиотеку Pillow, создайте изображение, получите объект ImageDraw и нарисуйте круг через ellipse() в квадратной области. В новых версиях Pillow также есть метод circle(), но ellipse() остается универсальным и хорошо подходит для обучения
PIL — старое название библиотеки, а современный пакет называется Pillow. Устанавливается он как Pillow, а импортируется как PIL
Установка Pillow
python -m pip install Pillow
Проверьте импорт
from PIL import Image, ImageDraw
print("Pillow работает")
Если импорт прошел без ошибки, можно рисовать
Самый простой круг через ellipse()
from PIL import Image, ImageDraw
image = Image.new("RGB", (400, 400), "white")
draw = ImageDraw.Draw(image)
draw.ellipse((100, 100, 300, 300), fill="skyblue", outline="navy", width=4)
image.save("circle.png")
После запуска рядом с файлом появится circle.png. На белом фоне будет голубой круг с темной обводкой
Почему ellipse рисует круг
Метод ellipse() рисует эллипс внутри прямоугольной области. Если область квадратная, эллипс становится кругом
draw.ellipse((100, 100, 300, 300), fill="red")
Координаты (100, 100, 300, 300) задают рамку
100, 100— левый верхний угол рамки300, 300— правый нижний угол рамки- ширина рамки 200 пикселей
- высота рамки 200 пикселей
Поскольку ширина и высота одинаковые, получается круг
Если рамка не квадратная, получится овал
from PIL import Image, ImageDraw
image = Image.new("RGB", (500, 300), "white")
draw = ImageDraw.Draw(image)
draw.ellipse((50, 50, 450, 250), fill="lightgreen", outline="green", width=3)
image.save("oval.png")
Здесь ширина области больше высоты, поэтому получится овал. Для круга следите, чтобы ширина и высота рамки совпадали
Нарисовать круг по центру и радиусу
Новичку часто удобнее думать не рамкой, а центром и радиусом. Тогда рамку можно посчитать
from PIL import Image, ImageDraw
image = Image.new("RGB", (400, 400), "white")
draw = ImageDraw.Draw(image)
center_x = 200
center_y = 200
radius = 80
box = (
center_x - radius,
center_y - radius,
center_x + radius,
center_y + radius
)
draw.ellipse(box, fill="orange", outline="black", width=3)
image.save("circle_by_radius.png")
Так проще менять размер круга: достаточно изменить radius
Метод circle() в новых версиях Pillow
В новых версиях Pillow есть метод circle(), который принимает центр и радиус напрямую
from PIL import Image, ImageDraw
image = Image.new("RGB", (400, 400), "white")
draw = ImageDraw.Draw(image)
draw.circle((200, 200), 80, fill="orange", outline="black", width=3)
image.save("circle_method.png")
Но если код должен работать на разных версиях Pillow, ellipse() через bounding box остается более привычным и совместимым вариантом
Заливка, контур и толщина линии
У ellipse() есть несколько важных параметров
draw.ellipse(
(100, 100, 300, 300),
fill="yellow",
outline="black",
width=5
)
fillзадает цвет заливкиoutlineзадает цвет контураwidthзадает толщину контура
Если нужен только контур, уберите fill
draw.ellipse((100, 100, 300, 300), outline="red", width=6)
Если нужна только заливка без контура, уберите outline
draw.ellipse((100, 100, 300, 300), fill="red")
Нарисовать несколько кругов
from PIL import Image, ImageDraw
image = Image.new("RGB", (500, 300), "white")
draw = ImageDraw.Draw(image)
circles = [
(80, 150, 50, "red"),
(250, 150, 70, "green"),
(420, 150, 40, "blue")
]
for x, y, radius, color in circles:
box = (x - radius, y - radius, x + radius, y + radius)
draw.ellipse(box, fill=color)
image.save("many_circles.png")
Здесь каждый круг описан центром, радиусом и цветом. Такой подход удобен для генерации простых изображений
Частая проблема: круг обрезается
Если круг выходит за границы изображения, Pillow просто отрежет часть, которая не помещается
draw.ellipse((-50, -50, 100, 100), fill="red")
Часть круга окажется за пределами холста. Проверьте, что координаты рамки находятся внутри изображения
Для изображения (400, 400) координаты должны быть примерно в пределах от 0 до 400
Мини-практика
Создайте изображение 600 на 400 и нарисуйте три круга: красный, желтый и зеленый, как светофор
from PIL import Image, ImageDraw
image = Image.new("RGB", (600, 400), "white")
draw = ImageDraw.Draw(image)
colors = ["red", "yellow", "green"]
positions = [150, 300, 450]
for x, color in zip(positions, colors):
draw.ellipse((x - 50, 175 - 50, x + 50, 175 + 50), fill=color, outline="black", width=3)
image.save("traffic_light.png")
После запуска откройте файл traffic_light.png и проверьте, что круги не обрезались
Частые ошибки
Устанавливать PIL вместо Pillow
Современный пакет ставится командой python -m pip install Pillow, а импорт остается from PIL import ...
Передавать центр вместо рамки в ellipse
ellipse() ждет рамку (x0, y0, x1, y1), а не центр и радиус
Делать прямоугольную рамку и ждать круг
Если ширина и высота рамки разные, получится овал
Не сохранять изображение
Если не вызвать image.save("file.png"), файл не появится на диске
Что почитать дальше по Python
Если нужен общий маршрут по теме, откройте рубрику Python. Для соседних задач пригодятся эти разборы:
- Пайтон или Питон: как правильно произносить Python по-русски
- Face recognition Python: как установить и что делать при ошибках dlib
- Pandas и Matplotlib с Python: основы анализа данных
- Path в Python: как найти путь к файлу, папке и самому Python