在计算机视觉和图像处理领域,我们经常需要在图片上标记特定的区域,比如在人脸识别框出人脸、在目标检测中标出物体位置,或者仅仅是为了给图片加一个水印 Logo。其中,画圆是最基础也是最常用的操作之一。
今天,我们就来聊聊如何使用 Python 在图片上画出漂亮的圆形。我们将主要使用两个最流行的库:OpenCV 和 Pillow (PIL)。
一、 准备工作:安装依赖库
在开始之前,请确保你的环境中安装了必要的库。推荐使用 pip 安装:
bash
# 安装 OpenCV (功能最强大,推荐)
pip install opencv-python
# 安装 Pillow (轻量级,也很常用)
pip install Pillow
# 安装 NumPy (OpenCV 依赖它)
pip install numpy
同时,准备一张测试图片,假设我们将其命名为 test_image.jpg,并放在代码同级目录下。
二、 方法一:使用 OpenCV (cv2) ------ 行业标准
OpenCV 是计算机视觉领域的瑞士军刀。它的 cv2.circle() 函数非常高效,支持抗锯齿、填充、不同颜色等多种特性。
1. 基础代码示例
python
import cv2
import numpy as np
# 1. 读取图片
image = cv2.imread('test_image.jpg')
# 检查图片是否成功读取
if image is None:
print("错误:无法读取图片,请检查路径")
exit()
# 2. 定义圆的参数
center_coordinates = (300, 300) # 圆心坐标 (x, y)
radius = 100 # 半径
color = (0, 255, 0) # 颜色 (BGR 格式:蓝, 绿, 红),这里是绿色
thickness = 5 # 线条粗细 (-1 表示填充实心圆)
# 3. 画圆
# cv2.circle(图像, 圆心, 半径, 颜色, 粗细)
cv2.circle(image, center_coordinates, radius, color, thickness)
# 4. 显示图片
cv2.imshow('Image with Circle', image)
# 5. 保存图片
cv2.imwrite('result_opencv.jpg', image)
# 等待按键并关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
2. 核心参数详解
- 坐标系统 :OpenCV 使用的是 左上角为原点 (0,0) 的坐标系,向右是 X 轴正方向,向下是 Y 轴正方向。
- 颜色 (BGR) :注意!OpenCV 默认使用 BGR 顺序,而不是常见的 RGB。
(255, 0, 0)是蓝色(0, 255, 0)是绿色(0, 0, 255)是红色
- thickness (粗细) :
- 如果是正整数(如
5),表示边框的像素宽度。 - 如果是
-1,表示画一个实心圆。
- 如果是正整数(如
3. 进阶:画半透明圆
OpenCV 本身不直接支持透明度通道的混合,但我们可以通过 addWeighted 函数模拟半透明效果:
python
# 创建一个覆盖层
overlay = image.copy()
cv2.circle(overlay, (300, 300), 100, (0, 255, 0), -1)
# 混合原图和覆盖层 (原图权重0.7, 覆盖层权重0.3)
alpha = 0.3
cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0, image)
三、 方法二:使用 Pillow (PIL) ------ 轻量简洁
如果你只是做简单的图片编辑,不需要复杂的计算机视觉算法,Pillow 是更轻量、更符合 Python 直觉的选择。
1. 基础代码示例
Pillow 画圆的逻辑稍微不同,它是通过 ellipse(椭圆)函数来画圆的,或者使用 ImageDraw 的圆弧方法。最简单的是用椭圆(当长宽相等时即为圆)。
python
from PIL import Image, ImageDraw
# 1. 打开图片
image = Image.open('test_image.jpg')
draw = ImageDraw.Draw(image)
# 2. 定义圆的参数
# Pillow 使用 [左上角x, 左上角y, 右下角x, 右下角y] 的坐标格式
x, y = 300, 300
radius = 100
bounding_box = [x - radius, y - radius, x + radius, y + radius]
# 3. 画圆
# outline 是边框颜色, width 是边框宽度
# 如果只想画边框,不要 fill 或者设置 fill=None
draw.ellipse(bounding_box, outline=(255, 0, 0), width=5)
# 如果想画实心圆,加上 fill 参数
# draw.ellipse(bounding_box, fill=(255, 0, 0), outline=None)
# 4. 显示图片 (会调用系统默认图片查看器)
image.show()
# 5. 保存图片
image.save('result_pillow.jpg')
2. Pillow vs OpenCV 对比
| 特性 | OpenCV (cv2) | Pillow (PIL) |
|---|---|---|
| 颜色格式 | BGR (容易踩坑) | RGB (符合直觉) |
| 坐标定义 | 圆心点 + 半径 | 左上角 + 右下角 (外接矩形) |
| 性能 | 极高 (C++底层) | 中等 (Python底层) |
| 依赖 | 较重 (NumPy等) | 轻量 |
| 适用场景 | 视频分析、实时处理、复杂算法 | 简单的图片编辑、Web后端生成图片 |
四、 实战案例:在人脸上画"眼镜"圆
假设我们要在图片中心画一个红色的实心圆,模拟一个简单的标记。
使用 OpenCV 实现:
python
import cv2
# 读取图片
img = cv2.imread('test_image.jpg')
h, w, _ = img.shape # 获取图片高宽
# 计算中心点
center = (w // 2, h // 2)
# 画一个红色的实心圆 (BGR: 0, 0, 255)
cv2.circle(img, center, 50, (0, 0, 255), -1)
# 添加文字说明
cv2.putText(img, "Center Point", (center[0] - 50, center[1] - 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
cv2.imshow('Center Marker', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
五、 常见问题 (FAQ)
Q1: 为什么我画的圆颜色不对?比如想画红色却变成了蓝色?
A: 这是 OpenCV 最经典的坑。OpenCV 使用 BGR 顺序。如果你习惯了 RGB,请记得转换:(R, G, B) -> (B, G, R)。或者在显示前转换色彩空间:cv2.cvtColor(img, cv2.COLOR_BGR2RGB)。
Q2: 图片显示一闪而过怎么办?
A : 在 cv2.imshow 之后,一定要加 cv2.waitKey(0),这行代码的意思是"等待任意按键输入",如果没有它,窗口会因为程序执行完毕而直接关闭。
Q3: 如何画一个只有轮廓没有填充的圆?
A:
- OpenCV:
thickness设为正数(如 1, 2, 5)。 - Pillow:
ellipse函数中设置fill=None或不写 fill,只写outline和width。
六、 总结
Python 在图片上画圆其实非常简单:
- 如果你追求性能 和专业功能 ,请首选 OpenCV 的
cv2.circle()。 - 如果你只是做简单的脚本 或Web图片生成 ,Pillow 的
ImageDraw.ellipse()更简单易用。
掌握了画圆,你就掌握了图像标注的基础。下一步,你可以尝试画矩形(cv2.rectangle)、多边形(cv2.polylines),甚至是贝塞尔曲线。
赶紧打开编辑器,给你的图片加上一个酷炫的圆吧!
如果你觉得这篇文章有帮助,欢迎点赞、收藏并分享给你的开发者朋友!