简介:本文详细介绍如何使用Python在照片上添加中文文字,涵盖基础实现、字体处理、布局优化及常见问题解决方案,适合开发者及设计人员参考。
在Python生态中,实现图片文字叠加的核心库为Pillow(PIL)和OpenCV,两者各有优势。Pillow是Python图像处理的标准库,支持TrueType/OpenType字体渲染,能精确控制文字位置、颜色和透明度;OpenCV更适合计算机视觉场景,但中文支持需额外处理。
Pillow方案优势:
ImageFont.truetype()加载中文字体文件(.ttf/.otc)OpenCV方案限制:
cv2.putText()的变通方案(如预渲染文字为图片)
pip install pillow numpy
from PIL import Image, ImageDraw, ImageFontimport numpy as npdef add_chinese_text(img_path, text, pos, font_path='simhei.ttf', font_size=40, color=(255,255,255)):"""在图片上添加中文文字:param img_path: 图片路径或numpy数组:param text: 要添加的文字:param pos: 文字位置(x,y):param font_path: 字体文件路径:param font_size: 字号:param color: 文字颜色(RGB):return: 处理后的图片"""# 处理输入类型if isinstance(img_path, np.ndarray):img = Image.fromarray(img_path)else:img = Image.open(img_path)# 创建绘图对象draw = ImageDraw.Draw(img)# 加载字体(关键步骤)try:font = ImageFont.truetype(font_path, font_size)except IOError:# 回退到默认字体(可能不支持中文)font = ImageFont.load_default()print("警告:未找到指定字体,使用默认字体可能导致中文显示异常")# 添加文字draw.text(pos, text, font=font, fill=color)return img# 使用示例if __name__ == '__main__':img = add_chinese_text('input.jpg','你好,世界!',(50, 50),font_path='msyh.ttc', # 微软雅黑字体font_size=60,color=(255, 0, 0))img.save('output.jpg')
def add_multiline_text(img, text, pos, max_width, font, **kwargs):"""自动换行的文字添加:param max_width: 最大行宽(像素)"""draw = ImageDraw.Draw(img)lines = []current_line = []current_width = 0for char in text:char_width, _ = draw.textsize(char, font=font)if current_width + char_width > max_width and current_line:lines.append(''.join(current_line))current_line = []current_width = 0current_line.append(char)current_width += char_widthif current_line:lines.append(''.join(current_line))y_pos = pos[1]for line in lines:line_width, line_height = draw.textsize(line, font=font)draw.text((pos[0], y_pos), line, font=font, **kwargs)y_pos += line_height
def add_text_with_outline(img, text, pos, font, fill_color, outline_color, outline_width=2):"""带描边的文字:param outline_width: 描边宽度(像素)"""draw = ImageDraw.Draw(img)# 先绘制描边(通过多次偏移实现)for x in range(-outline_width, outline_width+1):for y in range(-outline_width, outline_width+1):if (x, y) != (0, 0): # 中心点不绘制draw.text((pos[0]+x, pos[1]+y), text, font=font, fill=outline_color)# 再绘制填充draw.text(pos, text, font=font, fill=fill_color)
def add_text_with_shadow(img, text, pos, font, color, shadow_color=(0,0,0), offset=(3,3)):"""带阴影的文字:param offset: 阴影偏移量(x,y)"""draw = ImageDraw.Draw(img)# 先绘制阴影draw.text((pos[0]+offset[0], pos[1]+offset[1]), text, font=font, fill=shadow_color)# 再绘制文字draw.text(pos, text, font=font, fill=color)
OSError: cannot open resourcedef get_fallback_font():
“””获取可用中文字体的回退方案”””
system_fonts = {
‘Windows’: [‘C:/Windows/Fonts/msyh.ttc’, ‘C:/Windows/Fonts/simhei.ttf’],
‘Darwin’: [‘/Library/Fonts/Microsoft/MSYH.TTC’, ‘/System/Library/Fonts/PingFang.ttc’],
‘Linux’: [‘/usr/share/fonts/truetype/arphic/ukai.ttc’, ‘/usr/share/fonts/wenquanyi/wqy-zenhei.ttc’]
}
platform = os.nameif platform == 'nt':platform = 'Windows'elif platform == 'posix':platform = 'Darwin' if 'darwin' in os.uname().sysname.lower() else 'Linux'for font_path in system_fonts.get(platform, []):if os.path.exists(font_path):return font_pathreturn None
#### 2. 文字显示不全- **原因**:文字框超出图片边界- **解决方案**:1. 计算文字尺寸后动态调整位置:```pythondef get_text_size(text, font):"""获取文字尺寸"""from PIL import ImageDrawdummy_img = Image.new('RGB', (1,1))draw = ImageDraw.Draw(dummy_img)return draw.textsize(text, font=font)
批量处理:对多张图片使用相同字体时,避免重复加载
class TextAdder:def __init__(self, font_path, font_size):self.font = ImageFont.truetype(font_path, font_size)def add_text(self, img, text, pos, **kwargs):draw = ImageDraw.Draw(img)draw.text(pos, text, font=self.font, **kwargs)return img
import argparsefrom PIL import Imageclass WatermarkGenerator:def __init__(self, font_path='simhei.ttf'):self.font_path = font_pathdef add_watermark(self, input_path, output_path, text, position=(10,10),font_size=30, color=(255,255,255), opacity=1.0):"""添加半透明水印:param opacity: 透明度(0.0-1.0)"""img = Image.open(input_path).convert('RGBA')txt = Image.new('RGBA', img.size, (255,255,255,0))font = ImageFont.truetype(self.font_path, font_size)draw = ImageDraw.Draw(txt)draw.text(position, text, font=font, fill=(255,255,255,int(255*opacity)))result = Image.alpha_composite(img, txt)if img.mode != 'RGB':result = result.convert('RGB')result.save(output_path)if __name__ == '__main__':parser = argparse.ArgumentParser(description='图片中文水印添加工具')parser.add_argument('input', help='输入图片路径')parser.add_argument('output', help='输出图片路径')parser.add_argument('--text', default='机密文件', help='水印文字')parser.add_argument('--font', default='simhei.ttf', help='字体文件路径')parser.add_argument('--size', type=int, default=30, help='字号')parser.add_argument('--pos', nargs=2, type=int, default=[10,10], help='位置(x y)')parser.add_argument('--color', nargs=3, type=int, default=[255,255,255], help='颜色(R G B)')parser.add_argument('--opacity', type=float, default=0.7, help='透明度(0-1)')args = parser.parse_args()generator = WatermarkGenerator(args.font)generator.add_watermark(args.input,args.output,args.text,position=tuple(args.pos),font_size=args.size,color=tuple(args.color),opacity=args.opacity)
字体管理:
fonts/目录font_tools库检查字体支持的字符集性能优化:
错误处理:
IOError处理字体加载失败扩展性设计:
通过以上方法,开发者可以构建从简单文字叠加到专业级图文混排的完整解决方案。实际应用中,可根据具体需求组合使用基础功能和进阶技巧,实现高效的图片文字处理流程。