低秩字典学习实战:DICTOL图像去噪实验与源码解析
2026/10/6 10:43:03
欢迎来到第42天!
在日常工作中,我们经常需要处理图片:把 100 张大图缩小成缩略图、给证件照换底色、或者给公司所有的宣传图批量加上水印。如果一张张手动用 PS 处理,那真是要累断手。
Python 有一个非常强大的图像处理库——Pillow(PIL Fork)。它提供了广泛的文件格式支持、强大的图像处理能力,API 却非常简单易用。有了它,你就是代码界的修图师。
本节内容:
Pillow 是 Python Imaging Library (PIL) 的一个友好分支,依然使用PIL作为包名。
安装:
pipinstallPillow我们需要一张测试图片(假设名为test.jpg)。
fromPILimportImage# 1. 打开图片# img 是一个 Image 对象try:img=Image.open("test.jpg")exceptFileNotFoundError:print("图片未找到,请准备一张 test.jpg")exit()# 2. 查看属性print(f"格式:{img.format}")# JPEGprint(f"尺寸:{img.size}")# (1920, 1080) -> (宽, 高)print(f"模式:{img.mode}")# RGB# 3. 显示图片 (会调用系统默认图片查看器打开)img.show()# 另存为 PNGimg.save("test.png")# 转换模式 (如转为灰度图)# 'L' 表示灰度模式grey_img=img.convert("L")grey_img.save("test_grey.jpg")改变图片大小是刚需。Pillow 提供了resize和thumbnail两种方法。
# 1. resize: 强制改变大小 (可能会变形)# 注意参数是一个元组 (width, height)new_img=img.resize((300,200))new_img.show()# 2. thumbnail: 等比缩放 (制作缩略图)# 它会原地修改对象,且保持长宽比,不会超过指定尺寸img.thumbnail((300,300))img.save("thumbnail.jpg")# 定义裁剪区域: (左, 上, 右, 下)# 坐标原点 (0,0) 在左上角box=(100,100,500,500)region=img.crop(box)region.show()# 旋转 45 度img.rotate(45).show()# 左右镜像翻转img.transpose(Image.FLIP_LEFT_RIGHT).show()# 上下翻转# img.transpose(Image.FLIP_TOP_BOTTOM).show()想给照片加点特效?ImageFilter模块内置了多种滤镜。
fromPILimportImageFilter# 高斯模糊 (Radius 指定模糊程度)blur_img=img.filter(ImageFilter.GaussianBlur(radius=5))blur_img.show()# 轮廓滤镜 (也就是线稿风格)contour_img=img.filter(ImageFilter.CONTOUR)contour_img.show()# 锐化sharp_img=img.filter(ImageFilter.SHARPEN)这是最实用的功能之一。我们需要用到ImageDraw(画笔) 和ImageFont(字体)。
fromPILimportImage,ImageDraw,ImageFont# 1. 打开底图base_img=Image.open("test.jpg")# 2. 创建一个可以在 base_img 上绘画的对象draw=ImageDraw.Draw(base_img)# 3. 加载字体# Windows 字体路径通常在 C:/Windows/Fonts/# Mac/Linux 请替换为你的字体路径# 如果找不到字体,可以用默认字体 load_default(),但不支持中文try:# 这里的 50 是字号font=ImageFont.truetype("arial.ttf",50)exceptIOError:font=ImageFont.load_default()# 4. 绘制文字# xy: 坐标, text: 内容, fill: 颜色(RGB), font: 字体text="Copyright @ Python"draw.text((50,50),text,fill=(255,0,0),font=font)# 5. 保存base_img.show()base_img.save("watermarked.jpg")我们要写一个脚本,自动遍历images文件夹下的所有图片,在右下角加上半透明的水印,并保存到output文件夹。
importosfromPILimportImage,ImageDraw,ImageFontdefadd_watermark(input_path,output_path,text="Python Pro"):try:# 打开图片并转为 RGBA (支持透明度)img=Image.open(input_path).convert("RGBA")width,height=img.size# 创建一个透明的图层用于画水印txt_layer=Image.new("RGBA",img.size,(255,255,255,0))draw=ImageDraw.Draw(txt_layer)# 设置字体 (尽量找个存在的字体文件)try:font_size=int(width/20)# 根据图片宽度动态调整字号font=ImageFont.truetype("arial.ttf",font_size)except:font=ImageFont.load_default()# 计算文字大小 (getbbox 返回 (左, 上, 右, 下))bbox=draw.textbbox((0,0),text,font=font)text_width=bbox[2]-bbox[0]text_height=bbox[3]-bbox[1]# 计算位置 (右下角,留点边距)x=width-text_width-20y=height-text_height-20# 绘制水印 (最后一个参数 128 是透明度 alpha,0-255)# 注意:fill 的 RGBA 中 A=128 控制文字半透明draw.text((x,y),text,font=font,fill=(255,255,255,128))# 合并图层result=Image.alpha_composite(img,txt_layer)# 保存 (转回 RGB 存为 JPG,或者直接存 PNG)# 如果要存 JPG,必须转 RGB (因为 JPG 不支持透明)result.convert("RGB").save(output_path)print(f"处理完成:{output_path}")exceptExceptionase:print(f"处理失败{input_path}:{e}")defbatch_process():src_dir="images"dst_dir="output"ifnotos.path.exists(src_dir):print(f"请先创建{src_dir}文件夹并放入图片")returnifnotos.path.exists(dst_dir):os.makedirs(dst_dir)forfilenameinos.listdir(src_dir):iffilename.lower().endswith(('.png','.jpg','.jpeg')):in_path=os.path.join(src_dir,filename)out_path=os.path.join(dst_dir,filename)add_watermark(in_path,out_path)if__name__=="__main__":batch_process()Image.open报错UnidentifiedImageError?这通常是因为文件损坏,或者不是有效的图片格式(只是改了后缀名)。
JPG 不支持透明通道。如果你处理的是透明背景的 PNG,保存为 JPG 时透明部分会变成黑色。解决方法是保存为 PNG,或者在convert("RGB")之前创建一个白色背景层进行合并。
Pillow 的ImageGrab模块可以截屏。
fromPILimportImageGrab im=ImageGrab.grab()im.show()关键要点:
thumbnail,保持比例不失真。ImageDraw对象,如有透明度需求需使用 RGBA 模式。ImageOps或遮罩 Mask 技术)。Day 43:发送邮件 (smtplib)- 程序跑完了,结果怎么通知我?明天我们学习如何用 Python 自动发送邮件(包含附件和漂亮的 HTML 格式)。
系列导航: