Pillow ImagePalette 模块

下面为你提供 Pillow(PIL Fork)中 ImageStat 模块 的完整入门指南,包含功能介绍、核心方法、代码示例、实际应用场景及高级技巧。
(基于 Pillow ≥ 9.0,Python 3.8+)


1. 安装 Pillow

pip install --upgrade pillow

2. 基本导入

from PIL import Image, ImageStat

3. ImageStat 模块概述

ImageStat.Stat 是一个用于计算图像统计信息的类,支持单通道(灰度)或多通道(RGB/RGBA)图像的像素统计。它可以快速获取:

  • 基本统计:最小值、最大值、均值、方差、标准差
  • 通道统计:每个通道(R、G、B 或灰度)的独立统计
  • 像素计数:总像素数、非零像素计数
  • 直方图:像素值分布

适用场景

  • 图像亮度/对比度分析
  • 图像质量评估
  • 自动调整对比度/亮度
  • 图像分割预处理
  • 颜色分布分析

4. 核心类:ImageStat.Stat

4.1 初始化

img = Image.open("photo.jpg").convert("RGB")
stat = ImageStat.Stat(img)

参数

  • image:PIL 图像对象(支持 L, RGB, RGBA 等模式)
  • mask(可选):灰度蒙版,仅统计蒙版非零区域
  • extrema(可选):预计算的 (min, max) 元组

4.2 可用属性

属性说明返回值
extrema每个通道的最小/最大值[(min_r, max_r), (min_g, max_g), (min_b, max_b)]
count每个通道的像素总数[count_r, count_g, count_b]
sum每个通道像素值总和[sum_r, sum_g, sum_b]
sum2每个通道像素值平方和[sum2_r, sum2_g, sum2_b]
mean每个通道均值[mean_r, mean_g, mean_b]
median每个通道中值[median_r, median_g, median_b]
rms均方根(RMS)[rms_r, rms_g, rms_b]
var每个通道方差[var_r, var_g, var_b]
stddev每个通道标准差[stddev_r, stddev_g, stddev_b]

5. 基础用法示例

5.1 获取亮度均值(灰度图)

img = Image.open("photo.jpg").convert("L")  # 转灰度
stat = ImageStat.Stat(img)
print(f"亮度均值: {stat.mean[0]:.2f}")
print(f"亮度标准差: {stat.stddev[0]:.2f}")

5.2 RGB 通道统计

img = Image.open("photo.jpg").convert("RGB")
stat = ImageStat.Stat(img)
print(f"RGB 均值: R={stat.mean[0]:.2f}, G={stat.mean[1]:.2f}, B={stat.mean[2]:.2f}")
print(f"RGB 范围: {stat.extrema}")

5.3 使用蒙版统计局部区域

from PIL import ImageDraw

img = Image.open("photo.jpg").convert("RGB")
mask = Image.new("L", img.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((100, 100, 300, 300), fill=255)  # 圆形区域

stat = ImageStat.Stat(img, mask=mask)
print(f"圆形区域 RGB 均值: {stat.mean}")

6. 实际应用场景

6.1 自动亮度调整(基于均值)

def auto_brightness(img, target_mean=128):
    stat = ImageStat.Stat(img.convert("L"))
    current_mean = stat.mean[0]
    factor = target_mean / current_mean
    from PIL import ImageEnhance
    return ImageEnhance.Brightness(img).enhance(factor)

img = Image.open("dark.jpg")
adjusted = auto_brightness(img)
adjusted.save("auto_bright.jpg")

6.2 检测图像是否过暗/过亮

def is_image_too_dark_or_bright(img, dark_threshold=50, bright_threshold=200):
    stat = ImageStat.Stat(img.convert("L"))
    mean = stat.mean[0]
    if mean < dark_threshold:
        return "太暗"
    elif mean > bright_threshold:
        return "太亮"
    return "正常"

print(is_image_too_dark_or_bright(Image.open("photo.jpg")))

6.3 颜色分布分析(生成调色板)

def extract_palette(img, bins=16):
    img = img.convert("RGB").resize((100, 100))  # 缩小加速
    stat = ImageStat.Stat(img)
    hist = stat.histogram  # 获取直方图
    palette = []
    for i in range(0, 256, 256//bins):
        r = g = b = i
        palette.append((r, g, b))
    return palette

palette = extract_palette(Image.open("flower.jpg"))
print(f"调色板: {palette[:5]}")

7. 高级技巧

7.1 局部统计(人脸区域亮度分析)

def face_brightness(img, face_bbox):
    mask = Image.new("L", img.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.rectangle(face_bbox, fill=255)
    stat = ImageStat.Stat(img.convert("L"), mask=mask)
    return stat.mean[0]

# 示例:假设人脸区域
bbox = (150, 100, 350, 300)
mean_brightness = face_brightness(Image.open("portrait.jpg"), bbox)
print(f"人脸区域亮度: {mean_brightness:.2f}")

7.2 图像质量评估(标准差)

def assess_image_quality(img):
    stat = ImageStat.Stat(img.convert("L"))
    stddev = stat.stddev[0]
    if stddev < 10:
        return "低对比(模糊或单色)"
    elif stddev > 50:
        return "高对比(清晰或噪点多)"
    return "正常"

print(assess_image_quality(Image.open("photo.jpg")))

7.3 批量分析文件夹内图像

import os

def analyze_folder(folder):
    results = []
    for fname in os.listdir(folder):
        if fname.lower().endswith(('.png', '.jpg', '.jpeg')):
            img = Image.open(os.path.join(folder, fname)).convert("RGB")
            stat = ImageStat.Stat(img)
            results.append({
                "file": fname,
                "mean": [round(m, 2) for m in stat.mean],
                "stddev": [round(s, 2) for s in stat.stddev]
            })
    return results

# 使用
stats = analyze_folder("photos")
for r in stats:
    print(f"{r['file']}: 均值={r['mean']}, 标准差={r['stddev']}")

8. 完整示例:自动对比度增强

from PIL import Image, ImageStat, ImageEnhance

def auto_contrast(img):
    stat = ImageStat.Stat(img.convert("L"))
    min_val, max_val = stat.extrema[0]
    if max_val == min_val:
        return img  # 单色图跳过

    # 线性拉伸至 0~255
    factor = 255 / (max_val - min_val)
    img = ImageEnhance.Contrast(img).enhance(factor)
    return img

img = Image.open("low_contrast.jpg")
enhanced = auto_contrast(img)
enhanced.save("auto_contrast.jpg")

9. 性能优化建议

场景建议
大图统计resize 缩小(如 100×100)
重复统计缓存 ImageStat.Stat 对象
局部统计使用 maskcrop 限制区域
直方图分析结合 Image.histogram()

10. 常见问题 & 解决方案

问题原因解决
mean 返回空图像模式不支持(如 P转换为 LRGB
蒙版无效蒙版不是 L 模式mask.convert("L")
计算缓慢图像过大resize 或用 numpy 替代
统计值不准蒙版区域全黑检查蒙版非零像素

11. 官方文档

  • https://pillow.readthedocs.io/en/stable/reference/ImageStat.html

一键工具脚本:imgstat_tool.py

#!/usr/bin/env python3
import argparse
from PIL import Image, ImageStat

def main():
    parser = argparse.ArgumentParser(description="图像统计工具")
    parser.add_argument("image", help="输入图像路径")
    parser.add_argument("--mode", choices=["L", "RGB"], default="RGB")
    parser.add_argument("--bbox", nargs=4, type=int, help="区域统计 (x1 y1 x2 y2)")

    args = parser.parse_args()
    img = Image.open(args.image).convert(args.mode)

    if args.bbox:
        img = img.crop(args.bbox)

    stat = ImageStat.Stat(img)
    print(f"文件名: {args.image}")
    print(f"模式: {args.mode}")
    print(f"像素总数: {stat.count[0]}")
    print(f"均值: {[round(m, 2) for m in stat.mean]}")
    print(f"标准差: {[round(s, 2) for s in stat.stddev]}")
    print(f"范围: {stat.extrema}")

if __name__ == "__main__":
    main()

使用

python imgstat_tool.py photo.jpg --mode L
python imgstat_tool.py photo.jpg --bbox 100 100 300 300

需要我帮你实现 图像质量自动分级、颜色分布可视化、区域亮度对比、批量统计报表 等功能吗?直接说需求,我给你完整代码!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注