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

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

    • 0. 前言
    • 1. CLAHE 自适应均衡
      • 1.1 应用场景
      • 1.2 实现过程
    • 2. 直方图反向投影
      • 2.1 应用场景
      • 2.2 实现过程
    • 3. 基于颜色的目标追踪
    • 小结
    • 系列链接

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 pltimg = 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 npimg = 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 npdef color_tracker(video_src=0):"""功能:基于 CamShift 的颜色追踪系统参数:video_src (int/str) - 视频设备索引或文件路径"""cap = cv2.VideoCapture(video_src)ret, frame = cap.read()# 1. 手动选定初始 ROIx, 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:breakhsv = 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 键退出breakcap.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)——轮廓检测详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86937.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于uniapp的老年皮肤健康管理微信小程序平台(源码+论文+部署+安装+售后)

感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,我会一一回复,希望帮助更多的人。 系统背景 近年来,我国人口老龄化进程不断加快,据国家统计局数据显示&#…

MySQL(106)如何设计分片键?

设计分片键(Sharding Key)是数据库分片的核心,它决定了将数据分配到不同分片的方式。一个好的分片键应该能够均衡地分布数据,避免热点问题,提高查询性能。下面将详细介绍如何设计分片键,并结合代码进行说明…

汽车一键启动升级手机控车

汽车一键启动升级手机控车实现手机远程启动,不改变原车任何功能且全部免接线。升级后原车遥控器能在有效范围内启动车辆。移动管家手机控车一键启动系统用手机远程控制,完美兼容原车遥控器。支持长安、别克、宝马、奥迪等众多系列车型,市场99…

【开源项目】「安卓原生3D开源渲染引擎」:Sceneform‑EQR

「安卓原生3D开源渲染引擎」:Sceneform‑EQR 渲染引擎 “那一夜凌晨3点,第一次提交 PR 的手在抖……”——我深刻体会这种忐忑与激动。 仓库地址:(https://github.com/eqgis/Sceneform-EQR)。 一、前言:开源对我意味着什么 DIY 的…

建造者模式 - Flutter中的乐高大师,优雅组装复杂UI组件!

痛点场景:复杂的对话框配置 假设你需要创建一个多功能对话框: CustomDialog(title: 警告,content: 确定要删除吗?,titleStyle: TextStyle(fontSize: 20, color: Colors.red),contentStyle: TextStyle(fontSize: 16),backgroundColor: Color…

基于Java+Spring Boot的大学校园生活信息平台

源码编号:S559 源码名称:基于Spring Boot的大学校园生活信息平台 用户类型:双角色,用户、管理员 数据库表数量:17 张表 主要技术:Java、Vue、ElementUl 、SpringBoot、Maven 运行环境:Wind…

C# .NET Framework 中的高效 MQTT 消息传递

介绍: 在当今互联互通的世界里,设备之间高效可靠的通信至关重要。MQTT(消息队列遥测传输)就是为此而设计的轻量级消息传递协议。本文将探讨 MQTT 是什么、它的优势以及如何在 .NET 框架中设置和实现它。最后,您将对 M…

nn.Embedding 和 word2vec 的区别

理解它们的关键在于​​区分概念层级和职责​​。 可以将它们类比为: ​​word2vec:​​ 一个​​专门制作高质量词向量模型的“工厂”​​。​​nn.Embedding:​​ 一个​​可存储、查找并训练词向量的“智能储物柜”​​(作为…

华为云Flexus+DeepSeek征文|​​华为云ModelArts Studio大模型 + WPS:AI智能PPT生成解决方案​

引言:告别繁琐PPT制作,AI赋能高效办公 ​​ 在商业汇报、学术研究、产品发布等场景中,制作专业PPT往往需要耗费大量时间进行内容整理、逻辑梳理和视觉美化。​​华为云ModelArts Studio大模型​​与​​WPS​​深度结合,推出AI-P…

【连接redis超时】

报错 客户端输出缓冲区超限 Client … scheduled to be closed ASAP for overcoming of output buffer limits 表示这些客户端(通过 psubscribe 命令进行发布订阅操作)的输出缓冲区超过了 Redis 配置的限制,Redis 会关闭这些客户端连接来避免…

PHP「Not enough Memory」实战排错笔记

目录 PHP「Not enough Memory」实战排错笔记 1. 背景 2. 快速定位 3. 为什么 5 MB 的图片能耗尽 128 MB? 3.1 粗略估算公式(GD) 4. 实际峰值监控 5. 解决过程 6. 最佳实践与防御措施 7. 总结 PHP「Not enough Memory」实战排错笔记 —…

Java垃圾回收机制和三色标记算法

一、对象内存回收 对于对象回收,需要先判断垃圾对象,然后收集垃圾。 收集垃圾采用垃圾收集算法和垃圾收集器。 判断垃圾对象,通常采用可达性分析算法。 引用计数法 每个对象设置一个引用计数器。每被引用一次,计数器就加1&am…

基于python网络数据挖掘的二手房推荐系统

基于网络数据挖掘的二手房推荐系统设计与实现 【摘要】 随着互联网技术在房地产行业的深入应用,线上房源信息呈爆炸式增长,给购房者带来了信息过载的挑战。为了提升二手房筛选的效率与精准度,本文设计并实现了一个基于网络数据挖掘的二手房推…

Java + 阿里云 Gmsse 实现 SSL 国密通信

前言 解决接口或页面仅密信浏览器(或 360 国密浏览器)能访问的问题 测试页面 测试网站-中国银行:https://ebssec.boc.cn/boc15/help.html 使用其他浏览器(google,edge等)打开 使用密信浏览器打开 解决…

国产数据库分类总结

文章目录 一、华为系数据库1. 华为 GaussDB 二、阿里系数据库1. 阿里云 OceanBase2. PolarDB(阿里云自研) 三、腾讯系数据库1. TDSQL(腾讯云)2. TBase(PostgreSQL增强版) 四、传统国产数据库1. 达梦数据库&…

解密闭包:函数如何记住外部变量

🧠 什么是闭包? 闭包是一个函数对象,它不仅记住它的代码逻辑,还记住了定义它时的自由变量(即非全局也非局部,但被内部函数引用的变量)。即使外部函数已经执行完毕,这些自由变量的值…

I2C协议详解及STM32 HAL库硬件I2C卡死问题分析

一、I2C协议详解 1. I2C协议概述 Inter-Integrated Circuit (I2C) 是由 Philips 半导体(现 NXP 半导体)于 1980 年代设计的一种同步串行通信总线协议。该协议采用半双工通信模式,支持多主从架构,专为短距离、低速率的芯片间通信…

HTTP协议-后端接收请求

起因就是不知道post这个请求体中这些格式有什么区别,后端又怎么去接收这些不同格式的内容 Get请求 get请求是比较简单的一类 正常的直接用参数接收(不写的话名字要匹配)或者RequestParam都可以接收,用对象绑定也可以 resultful…

HTML5 实现的圣诞主题网站源码,使用了 HTML5 和 CSS3 技术,界面美观、节日氛围浓厚。

以下是一个 HTML5 实现的圣诞主题网站源码,使用了 HTML5 和 CSS3 技术,界面美观、节日氛围浓厚。它包括: 圣诞树动画 🎄雪花飘落特效 ❄️圣诞祝福语 🎁响应式布局,适配移动端 你可以将代码保存为 index.…

Spring Cloud Bus 和 Spring Cloud Stream

Spring Cloud Bus 和 Spring Cloud Stream 都是 Spring Cloud 生态中的消息通信组件,但它们的定位和使用场景有显著区别: 1. Spring Cloud Bus 核心定位:分布式系统的消息广播(配置刷新、事件传播)。 典型场景&#x…