OpenCV计算机视觉实战(14)——直方图均衡化

发布于:2025-07-01 ⋅ 阅读:(19) ⋅ 点赞:(0)

0. 前言

在图像处理与计算机视觉领域,直方图技术是最直观且高效的像素分布分析工具。无论是提升低对比度图像的细节表现,还是基于颜色特征进行目标定位与追踪,直方图均衡化与反向投影方法都能发挥关键作用。本文将从 CLAHE 自适应直方图均衡、反向投影的颜色热力图生成,到结合 CAMShift 构建实时颜色追踪系统,掌握直方图在图像增强与目标跟踪中的实战应用。

1. CLAHE 自适应均衡

传统直方图均衡化在光照不均的图像中容易引入过曝或欠曝。CLAHE (Contrast Limited Adaptive Histogram Equalization) 通过在局部区域内进行增强,并对对比度设限,有效避免过增强,提升图像细节。

1.1 应用场景

  • 车载夜间摄像:不同路面反光、街灯位置不均,用全局均衡易引入过曝
  • 医疗影像:CT 射线图像局部对比度低,需在细小病灶区域提亮
  • 文档扫描:老旧书页局部发黄不一,用 CLAHE 能避免过度白化

1.2 实现过程

  • 将图像从 BGR 转为 LAB 色彩空间(因为亮度分量 L 更适合做增强)
  • L 通道应用 CLAHE
  • 合并增强后的 L 与原始 AB 通道
  • 转回 BGR 显示效果
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('1.jpeg')
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)

clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
cl = clahe.apply(l)
limg = cv2.merge((cl, a, b))
final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)

# 绘制直方图对比
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes[0,0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)); axes[0,0].set_title('Original')
axes[0,1].hist(l.ravel(), bins=256); axes[0,1].set_title('Original L Histogram')
axes[1,0].imshow(cv2.cvtColor(final, cv2.COLOR_BGR2RGB)); axes[1,0].set_title('CLAHE Enhanced')
axes[1,1].hist(cl.ravel(), bins=256); axes[1,1].set_title('CLAHE L Histogram')
for ax in axes.flatten(): ax.axis('off')
plt.tight_layout()
plt.show()

clahe
关键函数解析:

  • cv2.createCLAHE():创建 CLAHE 对象,clipLimit 控制对比度限制,tileGridSize 决定分块区域大小
  • cv2.cvtColor(..., cv2.COLOR_BGR2LAB):转换至 LAB 色彩空间,增强亮度 L 分量
  • clahe.apply():对灰度图或 L 通道应用 CLAHE
参数 含义 调参建议
clipLimit 对比度阈值,越大局部对比度增强越明显 2.0–4.0 之间,夜间图像可适当调高
tileGridSize 划分网格数,(8,8)→(16,16)细节块越小 块越小细节增强越多,但噪声也随之增强

2. 直方图反向投影

直方图反向投影 (Back Projection) 可理解为“颜色热力图”。给定某种颜色分布的感兴趣区域 (Region of Interest, ROI) (如皮肤颜色),它可以在整幅图像中估算每个像素属于该颜色的概率,常用于颜色追踪和皮肤检测。

2.1 应用场景

  • 智能零售:检测货架上某品牌包装色块
  • 安防监控:快速定位佩戴特定颜色制服的人员
  • 增强现实:实时识别并跟踪特定颜色的虚拟标记

2.2 实现过程

  • 1D vs 2D 直方图
    • 1D (只用 H 通道)运算快但易受光照影响
    • 2D (H + S 通道)更稳健,建议对肤色、品牌色、球类追踪均使用 2D
  • 后处理
    • 形态学闭运算:填补小孔洞,去除零星噪点
    • 高斯模糊卷积:平滑概率图,再阈值化能获得更连续的候选区域
  • 可视化建议
    • 将反向投影结果与原图叠加,用伪彩(如 applyColorMap) 突出高概率区域。
import cv2
import numpy as np

img = cv2.imread('1.jpeg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# ROI 取皮肤区域
x,y,w,h = 830,320,30,30
roi = hsv[y:y+h, x:x+w]

# 2D 直方图计算与归一化
roi_hist = cv2.calcHist([roi], [0,1], None, [180,256], [0,180,0,256])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# 反向投影
dst = cv2.calcBackProject([hsv], [0,1], roi_hist, [0,180,0,256], 1)
# 形态学闭运算
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
dst = cv2.morphologyEx(dst, cv2.MORPH_CLOSE, kernel)
# 伪彩叠加
heat = cv2.applyColorMap(dst, cv2.COLORMAP_JET)
overlay = cv2.addWeighted(img, 0.6, heat, 0.4, 0)

cv2.imshow('Back Projection Overlay', overlay)
cv2.waitKey(0)
cv2.destroyAllWindows()

直方图反向投影
关键函数解析:

  • cv2.calcHist(images, channels, mask, histSize, ranges) 用于计算图像的直方图,在 HSV 色彩空间中,通常使用二维直方图来分析色调 (Hue) 和饱和度 (Saturation) 的分布
    • images:输入图像,需以列表形式传入,例如 [image]
    • channels:用于计算直方图的通道索引列表,例如,在 HSV 空间中,[0, 1] 表示使用 HS 通道
    • mask:掩膜图像,若不使用掩膜,则为 None
    • histSize:每个通道的直方图大小(即 bin 的数量),例如 [180, 256] 表示 H 通道有 180binS 通道有 256bin
    • ranges:每个通道的取值范围。例如 [0, 180, 0, 256] 表示 H 通道取值范围为 0180S 通道为 0256
  • dst = cv2.calcBackProject(images, channels, hist, ranges, scale) 用于执行直方图反向投影,它根据给定的直方图在目标图像中查找匹配区域,返回一个概率图,表示每个像素匹配该直方图的概率
    • images:输入图像,需以列表形式传入,例如 [image]
    • channels:用于计算反向投影的通道索引列表,需与直方图的通道一致
    • hist:用于反向投影的直方图,通常是目标对象的颜色直方图
    • ranges:每个通道的取值范围,需与计算直方图时使用的范围一致
    • scale:可选的缩放因子,通常设为 1
  • cv2.normalize(src, dst, alpha, beta, norm_type) 用于将数组(如直方图)的值归一化到指定范围,这在进行直方图比较或反向投影前是一个重要的预处理步骤
    • src:输入数组,即待归一化的直方图
    • dst:输出数组,可以与 src 相同
    • alpha:归一化后数组的最小值
    • beta:归一化后数组的最大值
    • norm_type:归一化类型,常用可选值包括 cv2.NORM_MINMAX (将值缩放到指定范围)和 cv2.NORM_L1 (使数组的 L1 范数为 1

3. 基于颜色的目标追踪

在视频流或相机实时画面中,利用直方图反向投影与 CamShift 算法,实现对特定颜色(如球、手套)的连续追踪。
首先,读取视频流,手动框选或预设目标 ROI,并计算其 HSV 直方图模型。然后在主循环中,对每帧图像进行 HSV 转换、反向投影,再使用 CamShift 算法更新目标窗口位置。最后可视化结果,绘制追踪窗口并显示。

import cv2
import numpy as np

def color_tracker(video_src=0):
    """
    功能:基于 CamShift 的颜色追踪系统
    参数:
        video_src (int/str) - 视频设备索引或文件路径
    """
    cap = cv2.VideoCapture(video_src)
    ret, frame = cap.read()
    # 1. 手动选定初始 ROI
    x, y, w, h = cv2.selectROI("Select ROI", frame, False)
    cv2.destroyWindow("Select ROI")

    # 2. 计算 ROI 的 HSV 直方图模型
    hsv_roi = cv2.cvtColor(frame[y:y+h, x:x+w], cv2.COLOR_BGR2HSV)
    roi_hist = cv2.calcHist([hsv_roi], [0,1], None, [180,256], [0,180,0,256])
    cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
    track_window = (x, y, w, h)

    # 3. CamShift 参数
    term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

    while True:
        ret, frame = cap.read()
        if not ret:
            break
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        # 4. 反向投影
        backproj = cv2.calcBackProject([hsv], [0,1], roi_hist, [0,180,0,256], 1)
        # 5. CamShift 更新窗口
        ret_box, track_window = cv2.CamShift(backproj, track_window, term_crit)
        # 6. 绘制结果
        pts = cv2.boxPoints(ret_box)
        pts = np.int0(pts)
        cv2.polylines(frame, [pts], True, (0,255,0), 2)
        cv2.imshow("Color Tracking", frame)

        if cv2.waitKey(30) & 0xFF == 27:  # 按 ESC 键退出
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    color_tracker(0)

关键函数解析:

  • cv2.selectROI(windowName, img, showCrosshair):交互式选取 ROI 区域,返回 (x, y, w, h)
  • cv2.CamShift(probImage, window, criteria):基于反向投影概率图进行自适应均值迁移,返回新的边界框 ret_box (旋转矩形)和更新后的搜索窗口 track_window
  • cv2.boxPoints(rotatedRect):将 CamShift 返回的旋转矩形参数转换为四个顶点坐标,便于绘制多边形

小结

在本文中,我们系统性地介绍了 CLAHE 自适应直方图均衡化、直方图反向投影以及基于颜色追踪的目标定位系统。这些方法不仅能显著增强图像的视觉质量,还能为实际工程项目提供稳健的技术支撑。CLAHE 通过分块与对比度限幅,有效提升了局部细节;反向投影利用颜色概率分布快速筛选目标区域;颜色追踪系统则将上述方法综合运用,实现了可扩展的动态目标跟踪方案。

系列链接

OpenCV计算机视觉实战(1)——计算机视觉简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)——计算机图像处理基础
OpenCV计算机视觉实战(4)——计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)——图像基础操作全解析
OpenCV计算机视觉实战(6)——经典计算机视觉算法
OpenCV计算机视觉实战(7)——色彩空间详解
OpenCV计算机视觉实战(8)——图像滤波详解
OpenCV计算机视觉实战(9)——阈值化技术详解
OpenCV计算机视觉实战(10)——形态学操作详解
OpenCV计算机视觉实战(11)——边缘检测详解
OpenCV计算机视觉实战(12)——图像金字塔与特征缩放
OpenCV计算机视觉实战(13)——轮廓检测详解


网站公告

今日签到

点亮在社区的每一天
去签到