费曼学习法4 - 画笔生花:图像的绘图与文字 (创意篇)

第四篇:画笔生花:图像的绘图与文字 (创意篇)

开篇提问:

你有没有想过,在照片上涂鸦,或者给图片加上可爱的文字,让它们变得独一无二? 就像在纸上绘画一样,我们也可以在图像上“画画”和“写字”! PIL 库就为我们提供了这样的“画笔”和“颜料”,让我们可以在图像上自由创作,添加各种个性化的元素和信息。 今天,就让我们拿起 PIL 的“画笔”,一起在图像上“画”出精彩,“写”出创意!

核心概念讲解 (费曼式解释):

  1. ImageDraw 模块: “我们的数字画布和画笔”

    想要在图像上绘图,首先我们需要一个 “画布” 和一套 “画笔”。 PIL 库的 ImageDraw 模块就扮演着这样的角色。 它就像一个 绘图工具箱,里面装满了各种绘图工具,可以让我们在 PIL 图像对象上绘制各种图形和文字。

    要使用 ImageDraw 模块,首先需要 创建一个 Draw 对象,这个对象就相当于我们的 “画布”,所有的绘图操作都会在这个画布上进行。 创建 Draw 对象很简单,只需要导入 ImageDraw 模块,并调用 ImageDraw.Draw(img) 函数,传入你要绘图的 PIL 图像对象 img 就可以了。

    from PIL import Image, ImageDraw
    
    # 打开一张图片作为画布
    image_path = "your_image.jpg"
    img = Image.open(image_path)
    
    # 创建 Draw 对象,img 就是我们的画布
    draw = ImageDraw.Draw(img)
    
    # 接下来我们就可以使用 draw 对象进行各种绘图操作了!
    
  2. 绘制基本图形: “点线面,绘出万千世界”

    有了画布和画笔,我们就可以开始绘制各种基本图形了。 ImageDraw 模块提供了丰富的绘图函数,可以绘制 点、线、矩形、椭圆、多边形 等各种基本形状。 就像我们小时候用铅笔和尺子画画一样,只不过现在我们用的是数字画笔!

    • 点 (Point): “星星点点,勾勒细节”

      draw.point(xy, fill=color) 函数用于绘制 xy 参数是点的 坐标,可以是一个 坐标元组 (x, y),或者一个 坐标列表 [(x1, y1), (x2, y2), ...],可以一次绘制多个点。 fill 参数是点的 颜色

      # 绘制一个红色的点 (坐标 (100, 100))
      draw.point((100, 100), fill="red")
      
      # 绘制多个绿色的点 (坐标 (150, 150), (200, 200), (250, 250))
      draw.point([(150, 150), (200, 200), (250, 250)], fill="green")
      
    • 线 (Line): “一笔划过,连接你我”

      draw.line(xy, fill=color, width=width) 函数用于绘制 线段折线xy 参数是 线段的端点坐标折线的顶点坐标,可以是一个 坐标列表 [(x1, y1), (x2, y2)] (线段)[(x1, y1), (x2, y2), (x3, y3), ...] (折线)。 fill 参数是线的 颜色width 参数是线的 宽度 (像素)。

      # 绘制一条蓝色的直线 (从 (50, 50) 到 (300, 50),宽度 3 像素)
      draw.line([(50, 50), (300, 50)], fill="blue", width=3)
      
      # 绘制一条紫色的折线 (连接 (50, 100), (100, 150), (150, 100), (200, 150))
      draw.line([(50, 100), (100, 150), (150, 100), (200, 150)], fill="purple")
      
    • 矩形 (Rectangle): “方方正正,规规矩矩”

      draw.rectangle(xy, fill=color, outline=outline_color, width=outline_width) 函数用于绘制 矩形xy 参数是矩形的 左上角和右下角坐标,是一个 坐标元组 (x0, y0, x1, y1)fill 参数是矩形的 填充颜色 (可以为空,表示空心矩形), outline 参数是矩形的 边框颜色width 参数是矩形的 边框宽度 (像素)。

      # 绘制一个黄色的实心矩形 (左上角 (100, 200),右下角 (200, 300))
      draw.rectangle((100, 200, 200, 300), fill="yellow")
      
      # 绘制一个红色边框的空心矩形 (左上角 (250, 200),右下角 (350, 300),边框宽度 5 像素)
      draw.rectangle((250, 200, 350, 300), outline="red", width=5)
      
    • 椭圆 (Ellipse): “圆润饱满,婀娜多姿”

      draw.ellipse(xy, fill=color, outline=outline_color, width=outline_width) 函数用于绘制 椭圆 (包括圆形)。 xy 参数是椭圆的 外接矩形的左上角和右下角坐标,也是一个 坐标元组 (x0, y0, x1, y1)。 其他参数 fill, outline, widthdraw.rectangle() 函数类似。 如果外接矩形是正方形,则绘制的是圆形。

      # 绘制一个橙色的实心椭圆 (外接矩形 左上角 (50, 350),右下角 (200, 450))
      draw.ellipse((50, 350, 200, 450), fill="orange")
      
      # 绘制一个绿色边框的空心圆形 (外接正方形 左上角 (250, 350),右下角 (350, 450),边框宽度 3 像素)
      draw.ellipse((250, 350, 350, 450), outline="green", width=3)
      
    • 多边形 (Polygon): “千变万化,自由组合”

      draw.polygon(xy, fill=color, outline=outline_color) 函数用于绘制 多边形xy 参数是多边形的 顶点坐标,是一个 坐标列表 [(x1, y1), (x2, y2), (x3, y3), ...]fill 参数是多边形的 填充颜色 (可以为空,表示空心多边形), outline 参数是多边形的 边框颜色

      # 绘制一个蓝色的实心三角形 (顶点坐标 (100, 500), (150, 600), (200, 500))
      draw.polygon([(100, 500), (150, 600), (200, 500)], fill="blue")
      
      # 绘制一个红色边框的空心五边形 (顶点坐标 ...)
      draw.polygon([(250, 500), (300, 520), (330, 580), (270, 600), (220, 550)], outline="red")
      
  3. 添加文字 (Text): “字字珠玑,传递信息”

    draw.text(xy, text, fill=color, font=font) 函数用于在图像上 添加文字xy 参数是 文字的左上角坐标text 参数是要 绘制的文本内容 (字符串)。 fill 参数是 文字颜色font 参数是 字体对象,需要使用 ImageFont.truetype()ImageFont.load_default() 函数 创建字体对象。 如果不指定 font 参数,则使用 默认字体 (通常不太美观,建议指定字体)。

    • 字体 (Font): “文字的 “外衣””

      字体决定了文字的 外观 风格。 PIL 库使用 ImageFont 模块来处理字体。 要使用 TrueType 字体文件 (.ttf, .otf),需要使用 ImageFont.truetype(font_path, size) 函数 加载字体文件font_path字体文件的路径size字体大小 (像素)。 如果你没有特定的字体文件,可以使用 ImageFont.load_default() 函数 加载默认字体

      from PIL import Image, ImageDraw, ImageFont
      
      # ... (打开图像, 创建 Draw 对象) ...
      
      # 1. 使用默认字体 (不推荐,通常比较丑)
      draw.text((50, 50), "Hello, PIL! (Default Font)", fill="black")
      
      # 2. 加载 TrueType 字体文件 (需要指定字体文件路径,例如 "arial.ttf")
      try:
          font_path = "arial.ttf" # 替换成你电脑上实际的字体文件路径
          font = ImageFont.truetype(font_path, size=36) # 字体大小 36 像素
          draw.text((50, 100), "Hello, PIL! (Arial Font)", fill="blue", font=font)
      except IOError:
          print("字体文件加载失败,请检查字体文件路径或安装字体")
          default_font = ImageFont.load_default() # 加载默认字体作为备选
          draw.text((50, 100), "Hello, PIL! (Default Font - Fallback)", fill="blue", font=default_font)
      
      
      # 3. 使用默认字体 (另一种方式)
      default_font = ImageFont.load_default()
      draw.text((50, 150), "Hello, PIL! (Default Font - Explicit)", fill="green", font=default_font)
      

      注意: arial.ttf 只是一个示例字体文件名,你需要 根据你的电脑系统和字体安装情况,选择一个实际存在的 TrueType 字体文件路径。 常见的字体文件路径可能在 Windows 的 C:\Windows\Fonts 目录下,或者 macOS 的 /Library/Fonts/System/Library/Fonts 目录下。 你可以根据你的操作系统搜索字体文件,并替换代码中的 font_path。 如果找不到合适的字体文件,可以先尝试使用 ImageFont.load_default() 默认字体。

代码实战 (动手练习):

我们继续使用 your_image.jpg 图片作为画布,练习绘制各种图形和添加文字。

from PIL import Image, ImageDraw, ImageFont

image_path = "your_image.jpg"
img = Image.open(image_path).convert("RGB") # 确保是 RGB 模式,方便颜色显示
draw = ImageDraw.Draw(img)

# 1. 绘制点
draw.point((50, 50), fill="red")
draw.point([(100, 50), (150, 50), (200, 50)], fill="green")

# 2. 绘制线
draw.line([(50, 100), (200, 100)], fill="blue", width=3)
draw.line([(50, 150), (100, 200), (150, 150), (200, 200)], fill="purple")

# 3. 绘制矩形
draw.rectangle((50, 250, 150, 350), fill="yellow")
draw.rectangle((200, 250, 300, 350), outline="red", width=5)

# 4. 绘制椭圆
draw.ellipse((50, 400, 150, 500), fill="orange")
draw.ellipse((200, 400, 300, 500), outline="green", width=3)

# 5. 绘制多边形
draw.polygon([(50, 550), (100, 650), (150, 550)], fill="blue")
draw.polygon([(200, 550), (250, 570), (280, 630), (220, 650), (170, 600)], outline="red")

# 6. 添加文字 (使用默认字体,你也可以尝试加载 TrueType 字体)
default_font = ImageFont.load_default()
draw.text((50, 700), "Hello, PIL! - Points, Lines, Shapes", fill="black", font=default_font)
draw.text((50, 750), "Drawing is Fun!", fill="purple", font=default_font)

# 保存结果
img.save("drawing_image.jpg")
print("绘图完成,已保存为 drawing_image.jpg")

动手练习:

  1. 修改代码:image_path = "your_image.jpg" 替换成你图片的实际路径。 尝试修改各种绘图函数的参数,例如坐标、颜色、宽度、字体等,观察绘图效果的变化。 尝试绘制更多不同的图形和文字。
  2. 运行代码: 保存代码为 .py 文件 (例如 draw_shapes_text.py),然后在终端中运行 python draw_shapes_text.py 命令。
  3. 查看效果: 查看生成的 drawing_image.jpg 文件,观察绘制的各种图形和文字。

案例应用:为图片添加水印,制作带有文字说明的图片

  1. 为图片添加水印

    水印通常用于 保护图片版权,或者 标记图片来源。 水印可以是 文字半透明的图像。 这里我们演示添加 半透明文字水印 的方法。

    from PIL import Image, ImageDraw, ImageFont
    
    image_path = "your_image.jpg"
    img = Image.open(image_path).convert("RGBA") # 转换为 RGBA 模式,支持透明度
    draw = ImageDraw.Draw(img, "RGBA") # Draw 对象也需要指定 "RGBA" 模式
    
    text = "© My Watermark" # 水印文字
    font_size = 48
    font = ImageFont.load_default() # 或者加载 TrueType 字体
    
    text_color = (255, 255, 255, 128) # 白色半透明 (RGBA: Red, Green, Blue, Alpha 透明度)  Alpha 值 128 表示半透明
    
    # 获取文字的宽度和高度,用于计算文字位置
    text_width, text_height = draw.textsize(text, font=font)
    
    # 计算水印位置 (例如,右下角,留出一些边距)
    margin = 10
    text_position = (img.width - text_width - margin, img.height - text_height - margin)
    
    # 绘制半透明水印文字
    draw.text(text_position, text, fill=text_color, font=font)
    
    # 保存带水印的图片
    img.save("watermarked_image.png") # 保存为 PNG 格式,保留透明度
    print("水印添加完成,已保存为 watermarked_image.png")
    

    代码解释:

    • img = Image.open(image_path).convert("RGBA"): 将图像转换为 RGBA 模式,RGBA 模式比 RGB 模式多了一个 Alpha 通道,用于表示 透明度。 只有在 RGBA 模式下,才能实现图像的半透明效果。
    • draw = ImageDraw.Draw(img, "RGBA"): 创建 Draw 对象时,也需要指定 "RGBA" 模式,确保绘图操作支持透明度。
    • text_color = (255, 255, 255, 128): 文字颜色使用 RGBA 值表示, 最后一个值 128 就是 Alpha 透明度值,取值范围 0-255,0 表示完全透明,255 表示完全不透明,128 表示半透明。
    • draw.textsize(text, font=font): draw.textsize() 方法可以 获取指定文字在指定字体下的宽度和高度 (像素)。 这可以帮助我们计算文字在图像中的位置,例如居中对齐、右下角对齐等。
    • 保存为 PNG 格式: 为了 保留透明度效果,水印图片通常需要 保存为 PNG 格式。 JPG 格式不支持透明度。
  2. 制作带有文字说明的图片

    我们可以结合绘图和文字,制作出带有各种文字说明的图片,例如 产品宣传图、海报、信息图 等。 下面是一个简单的例子,在图片下方添加一段文字说明。

    from PIL import Image, ImageDraw, ImageFont
    
    image_path = "your_image.jpg"
    img = Image.open(image_path).convert("RGB") # RGB 模式即可
    draw = ImageDraw.Draw(img)
    
    title_text = "Beautiful Scenery" # 图片标题
    description_text = "A breathtaking view of mountains and lake at sunset." # 图片描述
    font_title = ImageFont.load_default() # 标题字体
    font_description = ImageFont.load_default() # 描述字体
    title_color = "black"
    description_color = "gray"
    
    # 1. 绘制标题 (居中显示在图片上方)
    title_width, title_height = draw.textsize(title_text, font=font_title)
    title_position = ((img.width - title_width) // 2, 20) # 居中对齐,距离顶部 20 像素
    draw.text(title_position, title_text, fill=title_color, font=font_title)
    
    # 2. 绘制描述文字 (居中显示在图片下方)
    description_width, description_height = draw.textsize(description_text, font=font_description)
    description_position = ((img.width - description_width) // 2, img.height - description_height - 20 - 50) # 居中对齐,距离底部 20 + 50 像素
    draw.text(description_position, description_text, fill=description_color, font=font_description)
    
    # 3. 可以添加一些简单的装饰线条,例如在标题和图片之间、图片和描述文字之间
    line_y_top = title_position[1] + title_height + 10 # 标题下方 10 像素
    line_y_bottom = description_position[1] - 10 # 描述文字上方 10 像素
    draw.line([(50, line_y_top), (img.width - 50, line_y_top)], fill="lightgray", width=1) # 上方线条
    draw.line([(50, line_y_bottom), (img.width - 50, line_y_bottom)], fill="lightgray", width=1) # 下方线条
    
    
    # 保存带文字说明的图片
    img.save("image_with_text_description.jpg")
    print("带文字说明的图片制作完成,已保存为 image_with_text_description.jpg")
    

    代码解释:

    • 文字排版: 通过 draw.textsize() 方法获取文字尺寸,并结合图像尺寸,可以实现文字的 居中对齐、边缘对齐 等排版效果。 可以根据实际需求调整文字位置和间距。
    • 装饰线条: 使用 draw.line() 函数可以添加简单的装饰线条,例如分隔线、边框线等,增强图片的视觉效果。

费曼回顾 (知识巩固):

请你用自己的话,总结一下今天我们学习的图像绘图和文字添加的知识,包括:

  • ImageDraw 模块的作用是什么? 如何创建 Draw 对象?
  • 我们学习了哪些基本图形的绘制函数? 它们分别有什么参数?
  • 如何使用 draw.text() 函数添加文字? font 参数有什么作用? 如何加载字体文件?
  • 在水印添加和文字说明图片制作的案例中,我们是如何运用绘图和文字技巧的? RGBA 模式和透明度有什么作用? draw.textsize() 方法有什么用途?

像给你的朋友讲解一样,用最简单的语言解释这些概念,并结合代码示例和实际操作,帮助他们理解图像绘图和文字的乐趣。

课后思考 (拓展延伸):

  1. 尝试使用不同的字体文件,以及调整字体大小、颜色,看看文字效果的变化。
  2. 尝试绘制更复杂的图形,例如曲线、箭头、图标等。 (PIL 库还提供了一些更高级的绘图函数,例如 draw.arc(), draw.chord(), draw.pieslice() 等,可以查阅 PIL 官方文档了解更多)
  3. 尝试将绘图和文字技巧与其他图像处理技巧结合起来,例如图像缩放、裁剪、颜色调整等,创造更丰富的图像效果。
  4. 思考一下,图像绘图和文字添加还可以应用在哪些场景中? 例如,社交媒体图片制作、电子贺卡设计、信息可视化等等。 你有什么有趣的创意想法吗?

恭喜你!完成了 PIL 库的第四篇文章学习! 你已经掌握了图像绘图和文字的 “画笔”,可以开始在图像上自由创作,让你的图像作品充满创意和个性了! 下一篇文章,我们将学习如何给图像添加各种 “滤镜” 和进行图像增强,让你的图像更 “出色”,更有 “味道”! 敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值