Python 图像处理实战:Pillow 与 OpenCV 从入门到精通

Python 图像处理实战:Pillow 与 OpenCV 从入门到精通

专栏:Python 常用工具库实战教程 | 第三篇

适合人群:前端开发者、设计师、计算机视觉初学者


目录

  • [前言:Python 图像处理生态](#前言:Python 图像处理生态)
  • [第一章:Pillow ------ Python 图像处理入门](#第一章:Pillow —— Python 图像处理入门)
    • [1.1 Pillow 是什么](#1.1 Pillow 是什么)
    • [1.2 图像基础概念](#1.2 图像基础概念)
    • [1.3 图像的打开与创建](#1.3 图像的打开与创建)
    • [1.4 图像的保存与格式转换](#1.4 图像的保存与格式转换)
    • [1.5 图像裁剪与缩放](#1.5 图像裁剪与缩放)
    • [1.6 旋转与翻转](#1.6 旋转与翻转)
    • [1.7 绘图与文字](#1.7 绘图与文字)
    • [1.8 滤镜效果大全](#1.8 滤镜效果大全)
    • [1.9 颜色调整与增强](#1.9 颜色调整与增强)
    • [1.10 水印与合成](#1.10 水印与合成)
    • [1.11 实战案例:批量处理图片](#1.11 实战案例:批量处理图片)
  • [第二章:OpenCV ------ 计算机视觉利器](#第二章:OpenCV —— 计算机视觉利器)
    • [2.1 OpenCV 简介](#2.1 OpenCV 简介)
    • [2.2 图像读取与基本操作](#2.2 图像读取与基本操作)
    • [2.3 图像变换](#2.3 图像变换)
    • [2.4 图像滤波](#2.4 图像滤波)
    • [2.5 边缘检测](#2.5 边缘检测)
    • [2.6 颜色空间转换](#2.6 颜色空间转换)
    • [2.7 形态学操作](#2.7 形态学操作)
    • [2.8 轮廓检测](#2.8 轮廓检测)
  • [Pillow vs OpenCV 选择指南](#Pillow vs OpenCV 选择指南)

前言

在日常开发中,图像处理是一个非常实用的技能。无论是给照片加水印、批量调整图片尺寸,还是做人脸识别、图像分类,Python 都有对应的工具库。

Python 图像处理主要有两大工具:

对比维度 Pillow OpenCV
定位 通用图像处理 计算机视觉
优势 简单易用、功能丰富 高性能、算法丰富
安装 pip install pillow pip install opencv-python
颜色顺序 RGB BGR (注意!)
视频支持
GPU加速
学习难度 中高

本文将从 Pillow 开始,循序渐进地介绍图像处理的方方面面。


第一章:Pillow ------ Python 图像处理入门

1.1 Pillow 是什么

Pillow 是 Python Imaging Library (PIL) 的一个活跃分支。PIL 原版已经停止维护,Pillow 继承了 PIL 的所有功能并持续更新。

Pillow 支持:

  • 读写 30+ 种图像格式(PNG、JPEG、BMP、GIF、TIFF、WebP 等)
  • 图像缩放、旋转、裁剪、翻转
  • 色彩模式转换(RGB、RGBA、灰度、L、1 等)
  • 滤镜效果(模糊、锐化、边缘检测、浮雕等)
  • 图像增强(亮度、对比度、色彩饱和度)
  • 在图像上绘制文字和图形
  • 图像合成与叠加
bash 复制代码
pip install pillow
python 复制代码
from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageEnhance

1.2 图像基础概念

在学习图像处理之前,需要理解几个核心概念:

像素(Pixel)

像素是图像的最小单位。每张图片都是由大量像素排列组成的网格:

颜色模式
模式 说明 每像素字节数 用途
1 黑白(1-bit) 1/8 位图
L 灰度 1 黑白照片
RGB 红绿蓝三通道 3 彩色图片
RGBA RGB + 透明度 4 需要透明的图片
CMYK 印刷四色 4 印刷输出
P 调色板模式 1 GIF 动画
图像尺寸与分辨率
python 复制代码
# 图片尺寸 = 宽 × 高 (单位:像素)
# 1920 × 1080 = 2,073,600 像素 (约200万像素,即 2MP)

# DPI (Dots Per Inch) = 每英寸的像素数
# 72 DPI: 屏幕显示标准
# 150 DPI: 普通打印
# 300 DPI: 高质量打印

1.3 图像的打开与创建

打开已有图片
python 复制代码
from PIL import Image

# 打开图片
img = Image.open('photo.jpg')

# 查看图片信息
print(f"格式: {img.format}")      # JPEG, PNG 等
print(f"模式: {img.mode}")        # RGB, RGBA, L 等
print(f"尺寸: {img.size}")        # (宽度, 高度)
print(f"宽度: {img.width} 像素")
print(f"高度: {img.height} 像素")

# 查看 EXIF 信息(相机参数等)
exif = img._getexif()
if exif:
    for tag_id, value in exif.items():
        print(f"  {tag_id}: {value}")
创建新图片
python 复制代码
# 创建空白图片
img = Image.new('RGB', (800, 400), color='#2c3e50')

# 创建透明图片
img = Image.new('RGBA', (400, 300), (0, 0, 0, 0))

# 从像素数据创建
pixels = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]
img = Image.new('RGB', (3, 1))
img.putdata(pixels)

运行效果 ------ 创建自定义图形:

1.4 图像的保存与格式转换

Pillow 支持在不同格式之间自由转换:

python 复制代码
img = Image.open('source.png')

# 保存为不同格式
img.save('output.jpg', 'JPEG', quality=95)   # JPEG, 质量95%
img.save('output.bmp', 'BMP')                # BMP 无损
img.save('output.webp', 'WEBP')              # WebP 现代格式
img.save('output.gif', 'GIF')                # GIF
img.save('output.tiff', 'TIFF')              # TIFF 专业格式

各格式的文件大小对比(同一张图片):

复制代码
格式测试输出:
  PNG: .png → 1.9 KB     ← 无损压缩,体积中等
  JPEG: .jpg → 6.5 KB    ← 有损压缩,体积较大
  BMP: .bmp → 351.6 KB   ← 无压缩,体积巨大
  WEBP: .webp → 0.9 KB   ← 新一代格式,体积最小
格式 特点 适用场景 透明支持
PNG 无损压缩 网页图标、截图 支持
JPEG 有损压缩、高压缩率 照片存储 不支持
BMP 无压缩、原始数据 需要无损的场景 不支持
WebP 高压缩率、现代格式 网页优化 支持
GIF 动画、256色限制 表情包、动画 支持
TIFF 无损、多页 印刷、医疗影像 支持

1.5 图像裁剪与缩放

运行效果:


裁剪
python 复制代码
img = Image.open('photo.jpg')

# 裁剪区域: (左, 上, 右, 下)
cropped = img.crop((100, 50, 500, 350))
cropped.save('cropped.jpg')

裁剪坐标示意:

缩放
python 复制代码
# 指定尺寸缩放(可能变形)
resized = img.resize((400, 300))

# 高质量缩放(使用 LANCZOS 滤波器)
resized = img.resize((400, 300), Image.LANCZOS)

# 等比缩放(保持宽高比)
img.thumbnail((800, 800))  # 最大边不超过800

# 放大 2 倍
enlarged = img.resize((img.width * 2, img.height * 2), Image.LANCZOS)

缩放质量对比:

方法 说明 速度 质量
NEAREST 最近邻插值 最快 最差(锯齿)
BILINEAR 双线性插值 较快 一般
BICUBIC 双三次插值 较慢 较好
LANCZOS Lanczos 重采样 最慢 最好

1.6 旋转与翻转

运行效果:

python 复制代码
img = Image.open('photo.jpg')

# 旋转
rotated_45 = img.rotate(45)                    # 逆时针旋转45度
rotated_90 = img.rotate(90, expand=True)       # 旋转90度,扩展画布
rotated_free = img.rotate(30, expand=True, fillcolor='#2c3e50')  # 自定义背景色

# 翻转
flipped_h = img.transpose(Image.FLIP_LEFT_RIGHT)  # 水平翻转
flipped_v = img.transpose(Image.FLIP_TOP_BOTTOM)  # 垂直翻转

1.7 绘图与文字

Pillow 提供了 ImageDraw 模块,可以在图片上绘制各种图形和文字:

python 复制代码
from PIL import Image, ImageDraw, ImageFont

img = Image.new('RGB', (800, 400), '#ecf0f1')
draw = ImageDraw.Draw(img)

# 绘制矩形
draw.rectangle([50, 50, 200, 200], fill='#e74c3c', outline='white', width=3)

# 绘制椭圆
draw.ellipse([250, 50, 400, 200], fill='#3498db', outline='white', width=3)

# 绘制三角形
draw.polygon([(500, 200), (450, 50), (550, 50)], fill='#2ecc71', outline='white')

# 绘制圆角矩形
draw.rounded_rectangle([600, 50, 750, 200], radius=20, fill='#f39c12')

# 绘制线条
draw.line([(50, 250), (750, 250)], fill='#2c3e50', width=3)

# 绘制文字
font = ImageFont.truetype("msyh.ttc", 36)  # 微软雅黑36号
draw.text((200, 300), 'Hello Pillow!', fill='#2c3e50', font=font)

绘制函数速查:

方法 说明 参数
rectangle(xy, fill, outline, width) 矩形 (左,上,右,下)
ellipse(xy, fill, outline, width) 椭圆/圆 (左,上,右,下)
polygon(points, fill, outline) 多边形 [(x1,y1), (x2,y2), ...]
line(xy, fill, width) 线段 (x1,y1,x2,y2)
text(xy, text, fill, font) 文字 (x,y), 文本, 字体
arc(xy, start, end, fill, width) 弧线 角度(度)
chord(xy, start, end, fill, outline) 角度
pieslice(xy, start, end, fill) 扇形 角度
rounded_rectangle 圆角矩形 半径参数

1.8 滤镜效果大全

运行效果:

Pillow 内置了多种滤镜:

python 复制代码
from PIL import ImageFilter

img = Image.open('photo.jpg')

# 模糊
img_blur = img.filter(ImageFilter.GaussianBlur(radius=5))
img_blur = img.filter(ImageFilter.BLUR)           # 默认模糊

# 锐化
img_sharpen = img.filter(ImageFilter.SHARPEN)
img_sharpen = img.filter(ImageFilter.UnsharpMask(radius=2, percent=150))

# 边缘检测
img_edges = img.filter(ImageFilter.FIND_EDGES)

# 浮雕
img_emboss = img.filter(ImageFilter.EMBOSS)

# 轮廓
img_contour = img.filter(ImageFilter.CONTOUR)

# 细节增强
img_detail = img.filter(ImageFilter.DETAIL)

# 平滑
img_smooth = img.filter(ImageFilter.SMOOTH)
img_smooth_more = img.filter(ImageFilter.SMOOTH_MORE)

# 多重滤镜叠加
result = img.filter(ImageFilter.GaussianBlur(2)).filter(ImageFilter.SHARPEN)

所有内置滤镜一览:

滤镜 效果 适用场景
BLUR 模糊 背景虚化、隐私保护
CONTOUR 轮廓 素描效果
DETAIL 细节增强 照片锐化
EDGE_ENHANCE 边缘增强 图像增强
EDGE_ENHANCE_MORE 强边缘增强 更强的增强
EMBOSS 浮雕 艺术效果
FIND_EDGES 边缘检测 图像分析
SHARPEN 锐化 照片修复
SMOOTH 平滑 降噪
SMOOTH_MORE 更强平滑 更强降噪
GaussianBlur(n) 高斯模糊 可控模糊程度
UnsharpMask 反锐化蒙版 专业锐化

1.9 颜色调整与增强

运行效果:

python 复制代码
from PIL import ImageEnhance

img = Image.open('photo.jpg')

# 亮度调整 (1.0=原始, >1增强, <1减弱)
enhancer = ImageEnhance.Brightness(img)
bright = enhancer.enhance(1.5)  # 亮度提高50%

# 对比度调整
enhancer = ImageEnhance.Contrast(img)
contrast = enhancer.enhance(1.8)  # 对比度提高80%

# 色彩饱和度调整
enhancer = ImageEnhance.Color(img)
color = enhancer.enhance(2.0)  # 饱和度翻倍

# 锐度调整
enhancer = ImageEnhance.Sharpness(img)
sharp = enhancer.enhance(2.0)  # 锐度翻倍

# 综合调整
from PIL import ImageOps
img_auto = ImageOps.autocontrast(img)    # 自动对比度
img_equalize = ImageOps.equalize(img)    # 直方图均衡化
img_invert = ImageOps.invert(img.convert('RGB'))  # 反色
img_gray = ImageOps.grayscale(img)       # 转灰度

颜色调整效果表:

方法 调整值范围 效果 典型值
Brightness 0.0 ~ ∞ 明暗 1.2~1.5
Contrast 0.0 ~ ∞ 对比 1.3~1.8
Color 0.0 ~ ∞ 饱和度 1.5~2.5
Sharpness 0.0 ~ ∞ 清晰度 1.5~3.0

1.10 水印与合成

运行效果:

文字水印
python 复制代码
from PIL import Image, ImageDraw, ImageFont

def add_text_watermark(image_path, text, output_path, opacity=128):
    img = Image.open(image_path).convert('RGBA')
    watermark = Image.new('RGBA', img.size, (0, 0, 0, 0))
    draw = ImageDraw.Draw(watermark)

    font = ImageFont.truetype("msyh.ttc", 36)
    # 在右下角添加水印
    bbox = draw.textbbox((0, 0), text, font=font)
    x = img.width - bbox[2] - 20
    y = img.height - bbox[3] - 20
    draw.text((x, y), text, fill=(128, 128, 128, opacity), font=font)

    result = Image.alpha_composite(img, watermark)
    result.convert('RGB').save(output_path)
图片水印
python 复制代码
def add_image_watermark(image_path, watermark_path, output_path, position='bottom-right'):
    img = Image.open(image_path).convert('RGBA')
    watermark = Image.open(watermark_path).convert('RGBA')

    # 缩放水印
    wm_size = (img.width // 5, img.height // 5)
    watermark = watermark.resize(wm_size, Image.LANCZOS)

    # 计算位置
    if position == 'bottom-right':
        x = img.width - wm_size[0] - 20
        y = img.height - wm_size[1] - 20
    elif position == 'center':
        x = (img.width - wm_size[0]) // 2
        y = (img.height - wm_size[1]) // 2

    # 调整透明度
    watermark.putalpha(watermark.split()[3])

    # 合成
    img.paste(watermark, (x, y), watermark)
    img.convert('RGB').save(output_path)
图片拼接
python 复制代码
def combine_images(images, cols=2, padding=10, bg_color='#2c3e50'):
    rows_count = (len(images) + cols - 1) // cols
    max_w = max(img.width for img in images)
    max_h = max(img.height for img in images)

    combined_w = cols * max_w + (cols + 1) * padding
    combined_h = rows_count * max_h + (rows_count + 1) * padding

    combined = Image.new('RGB', (combined_w, combined_h), bg_color)

    for i, img in enumerate(images):
        row = i // cols
        col = i % cols
        x = padding + col * (max_w + padding)
        y = padding + row * (max_h + padding)
        combined.paste(img, (x, y))

    return combined

1.11 实战案例:批量处理图片

将前面学的技术组合起来,做一个实用的批量处理脚本:

python 复制代码
"""
批量处理图片:调整大小 + 加水印 + 转换格式
"""
from PIL import Image, ImageDraw, ImageFont, ImageEnhance, ImageFilter
import os

def batch_process(input_dir, output_dir, max_size=(1920, 1080),
                  watermark_text=None, output_format='JPEG'):
    """批量处理图片"""
    os.makedirs(output_dir, exist_ok=True)

    supported = {'.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff'}

    for filename in os.listdir(input_dir):
        ext = os.path.splitext(filename)[1].lower()
        if ext not in supported:
            continue

        filepath = os.path.join(input_dir, filename)
        try:
            img = Image.open(filepath)
        except Exception:
            print(f"跳过无法打开的文件: {filename}")
            continue

        # 1. 转为 RGB(去除透明通道)
        if img.mode in ('RGBA', 'P'):
            img = img.convert('RGB')

        # 2. 缩放到最大尺寸
        img.thumbnail(max_size, Image.LANCZOS)

        # 3. 轻微锐化
        img = img.filter(ImageFilter.SHARPEN)

        # 4. 自动对比度
        from PIL import ImageOps
        img = ImageOps.autocontrast(img)

        # 5. 添加水印
        if watermark_text:
            draw = ImageDraw.Draw(img)
            try:
                font = ImageFont.truetype("msyh.ttc", max(20, img.width // 30))
            except:
                font = ImageFont.load_default()
            text = watermark_text
            bbox = draw.textbbox((0, 0), text, font=font)
            x = img.width - (bbox[2] - bbox[0]) - 20
            y = img.height - (bbox[3] - bbox[1]) - 20
            draw.text((x, y), text, fill=(255, 255, 255), font=font)

        # 6. 保存
        name = os.path.splitext(filename)[0]
        output_path = os.path.join(output_dir, f"{name}.{output_format.lower()}")
        img.save(output_path, output_format, quality=90)
        print(f"已处理: {filename} → {output_path}")

# 使用
batch_process(
    input_dir='./photos',
    output_dir='./photos_processed',
    max_size=(1920, 1080),
    watermark_text='© 2025 MyBlog'
)

第二章:OpenCV ------ 计算机视觉利器

2.1 OpenCV 简介

OpenCV(Open Source Computer Vision Library)是世界上最大的计算机视觉库,支持 2500+ 种算法,覆盖图像处理、物体检测、人脸识别、OCR、姿态估计等领域。

bash 复制代码
pip install opencv-python
pip install opencv-contrib-python  # 包含额外模块
python 复制代码
import cv2
import numpy as np

重要区别 :OpenCV 使用 BGR 顺序(蓝-绿-红),而不是 PIL 的 RGB 顺序。这是一个常见的坑!

2.2 图像读取与基本操作

python 复制代码
import cv2

# 读取图片 (BGR 格式)
img = cv2.imread('photo.jpg')
img_color = cv2.imread('photo.jpg', cv2.IMREAD_COLOR)     # 彩色(默认)
img_gray = cv2.imread('photo.jpg', cv2.IMREAD_GRAYSCALE)  # 灰度

# 查看信息
print(f"形状: {img.shape}")       # (高度, 宽度, 通道数)
print(f"数据类型: {img.dtype}")   # uint8
print(f"像素总数: {img.size}")    # 高 × 宽 × 通道

# 显示图片
cv2.imshow('Image', img)
cv2.waitKey(0)       # 按任意键关闭
cv2.destroyAllWindows()

# 保存图片
cv2.imwrite('output.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])
像素操作
python 复制代码
# 读取单个像素 (BGR)
pixel = img[100, 200]    # [B, G, R] 值

# 修改像素
img[100, 200] = [255, 0, 0]  # 蓝色

# ROI(感兴趣区域)
roi = img[50:200, 100:300]   # (y1:y2, x1:x2)
img[50:200, 100:300] = 0     # 将该区域涂黑

# 使用掩码
mask = np.zeros(img.shape[:2], dtype=np.uint8)
mask[50:200, 100:300] = 255
result = cv2.bitwise_and(img, img, mask=mask)

2.3 图像变换

python 复制代码
import cv2
import numpy as np

img = cv2.imread('photo.jpg')

# 缩放
resized = cv2.resize(img, (400, 300))                    # 指定尺寸
scaled = cv2.resize(img, None, fx=0.5, fy=0.5)           # 按比例

# 旋转
h, w = img.shape[:2]
center = (w // 2, h // 2)
matrix = cv2.getRotationMatrix2D(center, angle=45, scale=1.0)
rotated = cv2.warpAffine(img, matrix, (w, h))

# 仿射变换
pts1 = np.float32([[0, 0], [w-1, 0], [0, h-1]])     # 原始3个点
pts2 = np.float32([[0, 0], [w-1, 0], [int(w*0.33), h-1]])  # 目标3个点
matrix = cv2.getAffineTransform(pts1, pts2)
warped = cv2.warpAffine(img, matrix, (w, h))

# 透视变换
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
perspective = cv2.warpPerspective(img, matrix, (300, 300))

2.4 图像滤波

python 复制代码
img = cv2.imread('photo.jpg')

# 均值模糊
blur = cv2.blur(img, (5, 5))

# 高斯模糊(更自然的模糊效果)
gaussian = cv2.GaussianBlur(img, (5, 5), 0)

# 中值滤波(去除椒盐噪声效果最好)
median = cv2.medianBlur(img, 5)

# 双边滤波(保边去噪)
bilateral = cv2.bilateralFilter(img, 9, 75, 75)

滤波效果对比:

方法 效果 噪声类型 边缘保留
均值模糊 整体模糊 高斯噪声
高斯模糊 平滑模糊 高斯噪声 一般
中值滤波 清晰保留细节 椒盐噪声
双边滤波 边缘清晰 所有噪声 最好

2.5 边缘检测

python 复制代码
img = cv2.imread('photo.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Canny 边缘检测(最常用)
edges = cv2.Canny(gray, threshold1=50, threshold2=150)

# Sobel 算子
sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
sobel = cv2.magnitude(sobel_x, sobel_y)

# Laplacian 算子
laplacian = cv2.Laplacian(gray, cv2.CV_64F)

# 边缘检测 + 二值化
_, binary = cv2.threshold(edges, 127, 255, cv2.THRESH_BINARY)

Canny 边缘检测的两个阈值参数:

  • threshold1: 低阈值 ------ 弱边缘
  • threshold2: 高阈值 ------ 强边缘
  • 两者之间的像素如果与强边缘相连,也会被保留

2.6 颜色空间转换

python 复制代码
img = cv2.imread('photo.jpg')

# BGR → 灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# BGR → RGB(与PIL互转时需要)
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# BGR → HSV(色相-饱和度-明度,颜色分割常用)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# BGR → LAB(感知均匀的颜色空间)
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

# HSV 颜色分割示例
lower_red = np.array([0, 100, 100])
upper_red = np.array([10, 255, 255])
mask = cv2.inRange(hsv, lower_red, upper_red)
red_only = cv2.bitwise_and(img, img, mask=mask)

常用颜色空间:

颜色空间 组成 优势 适用场景
BGR 蓝-绿-红 OpenCV 默认 通用
RGB 红-绿-蓝 通用标准 PIL/Web 互转
HSV 色相-饱和度-明值 颜色分割方便 颜色检测
Grayscale 灰度 单通道、计算快 边缘检测、OCR
LAB 明度-红绿-蓝黄 感知均匀 颜色对比
YCrCb 亮度-红差-蓝差 肤色检测 人脸识别

2.7 形态学操作

形态学操作基于数学形态学理论,常用于二值图像处理:

python 复制代码
import cv2
import numpy as np

# 先二值化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 定义结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 也可用圆形: cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))

# 腐蚀 ------ 收缩白色区域
eroded = cv2.erode(binary, kernel, iterations=1)

# 膨胀 ------ 扩张白色区域
dilated = cv2.dilate(binary, kernel, iterations=1)

# 开运算 ------ 先腐蚀后膨胀(去噪点)
opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)

# 闭运算 ------ 先膨胀后腐蚀(填孔洞)
closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)

# 形态学梯度 ------ 膨胀 - 腐蚀(提取边缘)
gradient = cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel)

# 顶帽 ------ 原图 - 开运算(提取小亮区域)
tophat = cv2.morphologyEx(binary, cv2.MORPH_TOPHAT, kernel)

# 黑帽 ------ 闭运算 - 原图(提取小暗区域)
blackhat = cv2.morphologyEx(binary, cv2.MORPH_BLACKHAT, kernel)

形态学操作效果图解:

2.8 轮廓检测

python 复制代码
import cv2

img = cv2.imread('shapes.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 查找轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE,
                                         cv2.CHAIN_APPROX_SIMPLE)

# 绘制所有轮廓
result = img.copy()
cv2.drawContours(result, contours, -1, (0, 255, 0), 2)

# 分析每个轮廓
for i, contour in enumerate(contours):
    # 面积
    area = cv2.contourArea(contour)
    # 周长
    perimeter = cv2.arcLength(contour, True)
    # 多边形近似
    epsilon = 0.02 * perimeter
    approx = cv2.approxPolyDP(contour, epsilon, True)
    # 外接矩形
    x, y, w, h = cv2.boundingRect(contour)
    # 外接圆
    (cx, cy), radius = cv2.minEnclosingCircle(contour)

    print(f"轮廓 {i}: 面积={area:.0f}, 周长={perimeter:.0f}, "
          f"顶点数={len(approx)}, 类形={'矩形' if len(approx)==4 else '其他'}")

    # 绘制外接矩形和圆
    cv2.rectangle(result, (x, y), (x+w, y+h), (255, 0, 0), 2)
    cv2.circle(result, (int(cx), int(cy)), int(radius), (0, 0, 255), 2)

轮廓分析速查:

函数 说明 返回值
contourArea(c) 轮廓面积 float
arcLength(c, True) 轮廓周长 float
approxPolyDP(c, e, True) 多边形近似 顶点数组
boundingRect(c) 外接矩形 (x, y, w, h)
minEnclosingCircle(c) 外接圆 (center, radius)
moments(c) 图像矩 字典
isContourConvex(c) 是否凸多边形 bool

选择指南

你的需求 推荐工具 原因
给图片加水印 Pillow 简单几行代码
批量调整图片大小 Pillow API 简洁、速度快
图片格式转换 Pillow 支持 30+ 格式
给图片加文字/图形 Pillow ImageDraw 完美支持
图片加滤镜效果 Pillow 内置丰富滤镜
人脸识别/检测 OpenCV 内置 Haar/DNN 模型
实时视频处理 OpenCV VideoCapture 支持
边缘检测/轮廓 OpenCV Canny/轮廓检测算法
图像分类/目标检测 OpenCV + 深度学习 DNN 模块支持模型推理
OCR 文字识别 OpenCV + Tesseract 预处理 + OCR

两者互转

在实际项目中,经常需要在 Pillow 和 OpenCV 之间转换:

python 复制代码
from PIL import Image
import cv2
import numpy as np

# Pillow → OpenCV
pil_img = Image.open('photo.jpg')
cv_img = np.array(pil_img)[:, :, ::-1]  # RGB → BGR

# OpenCV → Pillow
cv_img = cv2.imread('photo.jpg')
pil_img = Image.fromarray(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB))

下一篇预告:《Python 网络请求与爬虫实战:Requests + BeautifulSoup + Scrapy 从入门到实战》------ 学会从互联网上获取数据!

相关推荐
QCzblack3 小时前
期中考复现
开发语言·python
心中有国也有家3 小时前
PyTorch 适配 NPU:从 torch_npu 到 CANN 算子的全链路技术解析
人工智能·pytorch·python
盼小辉丶3 小时前
PyTorch强化学习实战(10)——强化学习高级组件
人工智能·pytorch·python·强化学习
EntyIU3 小时前
Python学习笔记
笔记·python·学习
wuxinyan1233 小时前
工业级大模型学习之路025:问题解决-检索质量全为0
人工智能·python·学习·langchain
weixin_408099673 小时前
2026 图片高清化 API 实战:AI超分辨率重建技术详解 + Python/Java/PHP/C#代码示例
图像处理·人工智能·python·超分辨率重建·石榴智能·图片变清晰·图片高清化api
财经资讯数据_灵砚智能3 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年5月24日
大数据·人工智能·python·信息可视化·自然语言处理
Cloud_Shy6183 小时前
Python 数据分析基础入门:《Excel Python:飞速搞定数据分析与处理》学习笔记系列(第十二章 用户定义函数 下篇)
python·plotly·数据分析·excel·numpy·pandas
Daydream.V3 小时前
【Python机器学习/计算机视觉】dlib库超详细入门教程(安装+人脸检测+特征点+人脸识别+视频实时处理)
python·机器学习·计算机视觉·dlib