You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现沿半圆形路径在图像周围绘制文本的方法问询

实现沿半圆形路径绘制文本(适配长短文本)

一、PIL 解决方案

核心思路是逐个字符计算位置与角度,彻底解决长短文本适配和居中对齐问题,视觉效果更自然。

实现步骤

  1. 定义半圆参数:圆心坐标、半径、角度范围(以上半圆为例,取90°到270°,对应弧度π/2到3π/2)。
  2. 均分角度:将半圆总角度按字符数量拆分,确保字符均匀分布。
  3. 逐字符绘制:计算每个字符在半圆上的坐标,旋转字符使其朝向圆心,最后将文本层与原图精准合并。

代码示例

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 20:35:30