OpenCV图像增强基础——图像金字塔、直方图与特征提取

一、前言

今天学习了 OpenCV 中几种常见的图像处理方法,包括图像金字塔、直方图、直方图均衡化、掩膜、角点检测、SIFT 特征提取以及图像旋转。

这些操作是计算机视觉的基础。在很多项目中,我们都需要先调整图像大小、增强对比度、提取关键特征,然后才能继续完成目标识别和图像匹配。


二、图像金字塔

图像金字塔是一种多尺度表示方法。它通过不断缩小或放大图像,得到不同分辨率的图片。

1. 图像下采样

下采样就是缩小图像,OpenCV 中使用 cv2.pyrDown()

复制代码
import cv2

image = cv2.imread(
    "face.png",
    cv2.IMREAD_GRAYSCALE
)

image_down_1 = cv2.pyrDown(image)
image_down_2 = cv2.pyrDown(image_down_1)

cv2.imshow("original", image)
cv2.imshow("down_1", image_down_1)
cv2.imshow("down_2", image_down_2)

cv2.waitKey(0)
cv2.destroyAllWindows()

每次调用 pyrDown(),图像的宽度和高度通常会缩小为原来的一半。例如:

复制代码
原图:800×600
第一次下采样:400×300
第二次下采样:200×150

下采样并不是简单地删除像素,而是会先对图像进行平滑处理,再缩小尺寸,这样可以减少锯齿和噪声。

2. 图像上采样

上采样就是放大图像:

复制代码
image_up = cv2.pyrUp(image)

cv2.imshow("up", image_up)
cv2.waitKey(0)
cv2.destroyAllWindows()

如果先缩小再放大:

复制代码
image_down = cv2.pyrDown(image)
image_restore = cv2.pyrUp(image_down)

虽然图像尺寸可能恢复,但清晰度通常无法完全恢复。这是因为下采样过程中已经丢失了一部分像素信息,放大时只能通过插值估计。

图像金字塔常用于:

  • 多尺度目标检测;
  • 图像融合;
  • 图像压缩;
  • 图片拼接;
  • 边缘和细节分析。

三、拉普拉斯金字塔

高斯金字塔保存不同尺寸的图像,拉普拉斯金字塔则保存图像在不同尺度之间的细节变化。

复制代码
down = cv2.pyrDown(image)
up = cv2.pyrUp(down)

laplacian = image - up

拉普拉斯图像主要保存边缘和细节信息。它可以用于图像重建和图像融合。

简单理解:

复制代码
高斯金字塔:保存图像的整体内容
拉普拉斯金字塔:保存图像的细节变化

四、图像直方图

图像直方图表示图像中像素值的分布情况。

对于灰度图:

  • 0 表示黑色;
  • 255 表示白色;
  • 横坐标表示灰度值;
  • 纵坐标表示像素数量。

如果直方图集中在左边,说明图像比较暗;如果集中在右边,说明图像比较亮;如果灰度分布范围很窄,说明图像对比度可能较低。

1. 使用Matplotlib绘制

复制代码
import matplotlib.pyplot as plt

phone = cv2.imread(
    "phone.png",
    cv2.IMREAD_GRAYSCALE
)

pixels = phone.ravel()

plt.hist(
    pixels,
    bins=256,
    range=(0, 256)
)

plt.show()

ravel() 可以将二维图像数组转换成一维数组,方便绘制直方图。

2. 使用OpenCV计算

复制代码
hist = cv2.calcHist(
    [phone],
    [0],
    None,
    [256],
    [0, 256]
)

plt.plot(hist)
plt.show()

cv2.calcHist() 的常见参数为:

复制代码
images:输入图像
channels:通道编号
mask:掩膜
histSize:区间数量
ranges:像素范围

如果不需要统计每一个灰度值,也可以将区间数量设置为 16:

复制代码
hist = cv2.calcHist(
    [phone],
    [0],
    None,
    [16],
    [0, 256]
)

这样会把 0 到 255 分成 16 个区间。


五、彩色图像直方图

OpenCV 使用 BGR 颜色顺序,因此可以分别计算三个颜色通道:

复制代码
image = cv2.imread("phone.png")

colors = ("b", "g", "r")

for i, color in enumerate(colors):
    hist = cv2.calcHist(
        [image],
        [i],
        None,
        [256],
        [0, 256]
    )

    plt.plot(
        hist,
        color=color
    )

plt.show()

三个通道分别是:

  • 0:蓝色;
  • 1:绿色;
  • 2:红色。

通过观察三个通道的直方图,可以了解图片中不同颜色的分布情况。


六、掩膜与局部直方图

掩膜可以指定图像中需要处理的区域。

复制代码
mask = np.zeros(
    phone.shape[:2],
    np.uint8
)

mask[50:350, 100:470] = 255

掩膜中的白色区域表示参与计算,黑色区域表示忽略。

提取指定区域:

复制代码
phone_mask = cv2.bitwise_and(
    phone,
    phone,
    mask=mask
)

cv2.imshow("mask_image", phone_mask)
cv2.waitKey(0)

计算局部区域的直方图:

复制代码
hist_mask = cv2.calcHist(
    [phone],
    [0],
    mask,
    [256],
    [0, 256]
)

plt.plot(hist_mask)
plt.show()

掩膜可以应用在:

  • 人脸区域分析;
  • 车牌区域分析;
  • 目标物体统计;
  • 忽略复杂背景。

七、直方图均衡化

当图像对比度较低时,可以使用直方图均衡化增强图像:

复制代码
woman = cv2.imread(
    "woman.png",
    cv2.IMREAD_GRAYSCALE
)

equalized = cv2.equalizeHist(woman)

查看原图和处理后的图像:

复制代码
result = np.hstack(
    (woman, equalized)
)

cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

直方图均衡化会重新分配灰度值,使原来集中在某个区域的像素分布更加分散,从而提高对比度。

不过,全局均衡化对光照不均匀的图片不一定理想。某些区域可能变得太亮,或者暗部细节仍然不明显。


八、自适应直方图均衡化

自适应均衡化会把图像划分成多个小区域,分别进行直方图处理。

复制代码
clahe = cv2.createCLAHE(
    clipLimit=1,
    tileGridSize=(16, 16)
)

clahe_image = clahe.apply(woman)

其中:

clipLimit 用于限制对比度增强程度;

tileGridSize 表示局部区域大小。

对比三种图像:

复制代码
result = np.hstack(
    (woman, equalized, clahe_image)
)

cv2.imshow("compare", result)
cv2.waitKey(0)

CLAHE 特别适合光照不均匀的图片,例如夜间照片、监控图像和医学影像。


九、角点检测

角点是图像中灰度变化明显的位置。例如,矩形的四个拐角就是典型角点。

使用 Harris 算法:

复制代码
image = cv2.imread(
    "huanghelou.png"
)

gray = cv2.cvtColor(
    image,
    cv2.COLOR_BGR2GRAY
)

dst = cv2.cornerHarris(
    gray,
    4,
    3,
    0.04
)

根据响应值筛选角点:

复制代码
image[
    dst > 0.01 * dst.max()
] = [0, 0, 255]

最后显示结果:

复制代码
cv2.imshow("corners", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

角点检测常用于:

图像配准;

物体定位;

图像拼接;

运动分析。


十、SIFT特征提取

SIFT 可以检测图像中的关键点,并计算对应的特征描述符。

复制代码
image = cv2.imread("man.png")
gray = cv2.cvtColor(
    image,
    cv2.COLOR_BGR2GRAY
)

sift = cv2.SIFT_create()
keypoints = sift.detect(gray)

绘制关键点:

复制代码
result = cv2.drawKeypoints(
    image,
    keypoints,
    None,
    flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
)

cv2.imshow("sift", result)
cv2.waitKey(0)

计算描述符:

复制代码
keypoints, descriptors = \
    sift.compute(
        gray,
        keypoints
    )

print(len(keypoints))
print(descriptors.shape)

SIFT 关键点不仅包含坐标,还包含大小、方向和响应值。描述符可以用于后续两张图片之间的特征匹配。


十一、图像旋转

使用 NumPy 旋转:

复制代码
rotated_1 = np.rot90(
    image,
    k=-1
)

rotated_2 = np.rot90(
    image,
    k=1
)

使用 OpenCV 旋转:

复制代码
clockwise = cv2.rotate(
    image,
    cv2.ROTATE_90_CLOCKWISE
)

counterclockwise = cv2.rotate(
    image,
    cv2.ROTATE_90_COUNTERCLOCKWISE
)

rotated_180 = cv2.rotate(
    image,
    cv2.ROTATE_180
)

图像旋转在处理手机照片、证件图片和竖屏图片时非常实用。


总结

本篇学习了 OpenCV 的图像增强和特征提取基础。

图像金字塔可以对图像进行多尺度处理;直方图可以分析像素分布;掩膜可以选择局部区域;直方图均衡化可以增强对比度;角点和 SIFT 可以提取图像中的关键特征;图像旋转则可以调整图片方向。

这些操作虽然看起来比较基础,但它们经常作为后续图像识别任务的预处理步骤。只有先把图片处理好,后面的轮廓检测、模板匹配和 OCR 识别才能取得更好的效果。

相关推荐
这张生成的图像能检测吗1 小时前
(论文速读)MANTIS:时间序列分类的轻量级基础模型
人工智能·时序模型·分类模型
u0103055272 小时前
AI Agent加速安卓应用快速落地
人工智能·新浪微博
angered2 小时前
「AI 应用 / AI Agent」行业日报 · 2026-08-21
人工智能
李昊哲小课2 小时前
大模型应用开发课程 —— 项目 09~12 完整教程
大数据·人工智能·大模型
xierui1231232 小时前
AI Agent 隐私架构:本地化重点为什么是登录态与执行权限
java·人工智能·网络安全·架构
u0103055272 小时前
昇腾AI赋能安卓智能助手
人工智能·笔记
回眸&啤酒鸭2 小时前
【回眸】Grok 4.6 核心能力落地与实战应用指南
大数据·人工智能
冬奇Lab2 小时前
Code Agent 解剖(07):外部工具怎么接进来?MCP 集成是怎么做的?
人工智能
日月新著2 小时前
微软2万人调查:天天用AI的你,为什么还是原地踏步?
人工智能·microsoft