Python实现沿半圆形路径在图像周围绘制文本的方法问询
实现沿半圆形路径绘制文本(适配长短文本)
一、PIL 解决方案
核心思路是逐个字符计算位置与角度,彻底解决长短文本适配和居中对齐问题,视觉效果更自然。
实现步骤
- 定义半圆参数:圆心坐标、半径、角度范围(以上半圆为例,取90°到270°,对应弧度π/2到3π/2)。
- 均分角度:将半圆总角度按字符数量拆分,确保字符均匀分布。
- 逐字符绘制:计算每个字符在半圆上的坐标,旋转字符使其朝向圆心,最后将文本层与原图精准合并。
代码示例
from PIL import Image, ImageDraw, ImageFont import math def draw_semicircle_text(base_img, text, font_path, font_size, radius, center, text_color=(0,0,0)): # 创建透明文本画布,与原图尺寸一致 text_img = Image.new("RGBA", base_img.size, (255,255,255,0)) draw = ImageDraw.Draw(text_img) font = ImageFont.truetype(font_path, font_size) # 上半圆的弧度范围 start_angle = math.pi / 2 end_angle = 3 * math.pi / 2 total_angle = end_angle - start_angle # 计算字符间的角度间隔 char_count = len(text) angle_step = total_angle / (char_count - 1) if char_count > 1 else 0 # 逐个绘制字符 for i, char in enumerate(text): current_angle = start_angle + i * angle_step # 计算字符在半圆上的坐标 x = center[0] + radius * math.cos(current_angle) y = center[1] + radius * math.sin(current_angle) # 旋转字符使其朝向圆心 rotate_angle = math.degrees(current_angle - math.pi/2) char_img = Image.new("RGBA", (font_size*2, font_size*2), (255,255,255,0)) char_draw = ImageDraw.Draw(char_img) char_draw.text((font_size, font_size), char, font=font, fill=text_color, anchor="mm") char_img = char_img.rotate(rotate_angle, expand=True) # 粘贴字符到对应位置,确保中心对齐 paste_x = int(x - char_img.width/2) paste_y = int(y - char_img.height/2) text_img.paste(char_img, (paste_x, paste_y), char_img) # 合并文本层与原图 result = Image.alpha_composite(base_img.convert("RGBA"), text_img) return result.convert("RGB") # 使用示例 if __name__ == "__main__": base_img = Image.open("your_base_image.png").convert("RGBA") result_img = draw_semicircle_text( base_img, "SHORT TEXT", "arial.ttf", 30, 150, (base_img.width//2, base_img.height//2 - 100) ) result_img.save("output.png")
方案优势
- 适配任意长度文本,字符均匀分布无拉伸失真
- 可精准控制圆心位置,轻松实现与原图目标对象的居中对齐
- 字符朝向圆心,视觉一致性更好
二、ImageMagick/Wand 改进方案
之前用distort方法对短文本效果差,是因为整体拉伸变形导致失真。改用逐字符定位+旋转的方式,彻底解决该问题。
Wand 代码示例
from wand.image import Image from wand.drawing import Drawing from wand.color import Color from wand.font import Font import math def draw_semicircle_text_wand(base_img_path, text, font_path, font_size, radius, center, text_color="black"): with Image(filename=base_img_path) as img: with Drawing() as draw: draw.font = Font(font_path, size=font_size) draw.fill_color = Color(text_color) # 上半圆角度范围(顺时针) start_angle = 90 end_angle = 270 total_angle = end_angle - start_angle char_count = len(text) angle_step = total_angle / (char_count - 1) if char_count > 1 else 0 for i, char in enumerate(text): current_angle = start_angle + i * angle_step # 计算字符坐标 x = center[0] + radius * math.cos(math.radians(current_angle)) y = center[1] + radius * math.sin(math.radians(current_angle)) # 旋转字符朝向圆心 draw.text(x, y, char, rotation=(current_angle - 90)) draw(img) img.save(filename="output_wand.png") # 使用示例 draw_semicircle_text_wand( "your_base_image.png", "LONG EXAMPLE TEXT HERE", "arial.ttf", 30, 150, (400, 300) )
关键注意事项
- 圆心坐标和半径需根据原图中目标对象的位置调整,确保文本围绕对象分布
- 优先选择无衬线字体,旋转后可读性更强
- 短文本禁止使用整体拉伸变形,逐字符定位是最优解
内容的提问来源于stack exchange,提问作者Danish Ejaz
相关产品推荐
相关产品推荐

