OpenCV计算机视觉实战(7)——色彩空间详解
OpenCV计算机视觉实战(7)——色彩空间详解
- 0. 前言
- 1. RGB/BGR 色彩空间
- 2. HSV / Lab 色彩空间
- 3. 颜色直方图分析与可视化
- 小结
- 系列链接
0. 前言
本文深入探讨了三种常见色彩空间:RGB/BGR
、HSV
与 CIELAB
,并介绍了 OpenCV
中色彩空间转换的方法与原理 。在 HSV
与 Lab
空间部分,演示了如何利用 HSV
进行色彩分割,以及使用 Lab
空间进行颜色校正与色差分析。最后,展示了如何使用 cv2.calcHist
计算颜色直方图,并结合 Matplotlib
对 BGR
通道直方图进行可视化分析,以支持图像增强和基于颜色的检索任务 。
1. RGB/BGR 色彩空间
OpenCV
默认采用 BGR
排序,而非 RGB
,这一设计最早源自 Windows BMP
格式的习惯,字节流自然排成 BGR
顺序。在内存中,图像以行主序 (row-major
) 方式存储,每个像素的三个通道连续排列。
由于 BGR
与 RGB
仅是通道顺序的差异,任何基于 NumPy
的切片和向量化操作都能以零拷贝方式高效实现格式转换,这也解释了为何 cv2.cvtColor
基于对内存指针的重解释而非像素重排 。
OpenCV
与其他使用 RGB
顺序的库(如 Matplotlib
)协同使用时,需要显式执行 cv2.COLOR_BGR2RGB
转换,避免色彩失真与输入格式不匹配的问题。
对于含透明通道 (Alpha
) 的图像,OpenCV
同样提供 cv2.COLOR_BGRA2RGBA
等变换,可一并处理多通道图像,并可借助 cv2.split/cv2.merge
做更灵活的透明度叠加。
import cv2
import matplotlib.pyplot as plt# 1) 使用 OpenCV 读取图像(默认为 BGR 格式)
img_bgr = cv2.imread('1.jpeg') # cv2.imread 默认读取 BGR 图像# 2) 使用 OpenCV 显示(正常显示 BGR)
# cv2.imshow('OpenCV BGR Display', img_bgr)
# cv2.waitKey(0)
# cv2.destroyAllWindows() # cv2.imshow 用于显示 BGR 图像# 3) 直接用 Matplotlib 显示(通道顺序不转换,会看到色彩错位)
plt.subplot(1,2,1)
plt.title('Matplotlib without Conversion')
plt.imshow(img_bgr) # plt.imshow 默认以 RGB 通道渲染, 直接显示 BGR 数组会出现蓝红通道颠倒
plt.axis('off')
# 4) 转换 BGR -> RGB
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # 高效通道重排,无数据拷贝# 5) 再次用 Matplotlib 显示(正确颜色)
plt.subplot(1,2,2)
plt.title('Matplotlib after cvtColor')
plt.imshow(img_rgb)
plt.axis('off')
plt.show()
关键函数解析:
cv2.imread(path)
:读取图像到NumPy
数组,默认按BGR
通道顺序加载plt.imshow(image)
:用Matplotlib
渲染图像时,默认将数组视为RGB
格式;若输入BGR
数组,将出现蓝红通道颠倒的现象cv2.cvtColor(src, code)
:执行高效的色彩空间转换,通过NumPy
视图操作避免额外拷贝
2. HSV / Lab 色彩空间
HSV
(Hue
, Saturation
, Value
) 将色相、饱和度与明度解耦,最早受人类视觉模型启发,色相环 (0°–360°
) 对应常见彩虹色谱,可直观地对单一色调进行阈值分割,尤其适合实时目标跟踪与交互式调色面板。通过 HSV
分割可稳定提取同一物体在光照变化下的轮廓,例如自动化装配线中对特定色标的检测。
CIELAB
(Lab
) 旨在实现感知均匀性,将明度 L*
与对立色轴 a*
(绿—红)、b*
(蓝—黄)分离,极大地简化了色差计算,在印刷质量控制与医学影像配色校正中具有极大优势。
在色彩校正流水线中,通常先将图像从 BGR
转换到 Lab
,然后对 L*
进行均衡化或 Gamma
校正,再重投影到 BGR
,以兼顾视觉亮度和色彩准确度。
OpenCV
提供了 cv2.COLOR_BGR2HSV
、cv2.COLOR_BGR2Lab
等转换方式,还支持将 HSV
、Lab
与 YCrCb
等多空间联合使用,满足不同任务的色彩分离需求。
接下来,使用交互式滑动条,使得 HSV
阈值可在运行时实时调整,适应多变光照环境。同时演示在 Lab
空间中对 L*
通道应用自适应直方图均衡化,可以在局部区域内提升对比度并抑制噪点 。最后,将原图、HSV
分割结果与 Lab
增强结果并排展示,便于直观对比三者在不同场景下的效果差异:
import cv2
import numpy as npdef nothing(x):pass# 读取原始图像
img = cv2.imread('1.jpeg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # BGR -> HSV# 创建滑动条窗口
cv2.namedWindow('HSV 调参')
for name, init in zip(['H_min','H_max','S_min','S_max','V_min','V_max'],[0, 179, 0, 255, 0, 255]
):max_val = 179 if 'H' in name else 255cv2.createTrackbar(name, 'HSV 调参', init, max_val, nothing) # 创建滑动条# Lab CLAHE 对象
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) # CLAHE 对比度限制while True:# 获取滑动条数值h_min = cv2.getTrackbarPos('H_min', 'HSV 调参')h_max = cv2.getTrackbarPos('H_max', 'HSV 调参')s_min = cv2.getTrackbarPos('S_min', 'HSV 调参')s_max = cv2.getTrackbarPos('S_max', 'HSV 调参')v_min = cv2.getTrackbarPos('V_min', 'HSV 调参')v_max = cv2.getTrackbarPos('V_max', 'HSV 调参')lower = np.array([h_min, s_min, v_min])upper = np.array([h_max, s_max, v_max])# HSV 分割mask = cv2.inRange(hsv, lower, upper) # 生成二值掩膜res_hsv = cv2.bitwise_and(img, img, mask=mask) # 掩膜与原图叠加# Lab 空间 CLAHE 增强lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab) # BGR -> Labl, a, b = cv2.split(lab) # 通道分离l_eq = clahe.apply(l) # 对 L* 通道应用lab_eq = cv2.merge([l_eq, a, b]) # 通道合并res_lab = cv2.cvtColor(lab_eq, cv2.COLOR_Lab2BGR) # Lab -> BGR# 并排展示原图 / HSV 分割 / Lab 增强combined = np.hstack((img, res_hsv, res_lab))cv2.imshow('原图 | HSV 分割 | Lab CLAHE 增强', combined) # 同一窗口对比# 按 Esc 键退出并保存结果if cv2.waitKey(1) & 0xFF == 27:# 保存各阶段结果cv2.imwrite('result_original.jpg', img) # 保存原始图像cv2.imwrite('result_hsv_segmentation.png', res_hsv) # 保存 HSV 分割结果 cv2.imwrite('result_lab_clahe.jpg', res_lab) # 保存 Lab CLAHE 增强结果cv2.imwrite('result_comparison.png', combined) # 保存并排对比图breakcv2.destroyAllWindows()
关键代码解析:
cv2.createTrackbar(name, win, val, max, callback)
:在指定窗口中创建命名为name
的滑动条,用于获取范围[0,max]
内的整型数值,实时回调函数callback
获取最新位置cv2.inRange(src, lowerb, upperb)
:对每个像素的三通道值与阈值数组lowerb / upperb
进行比较,符合条件的像素输出255
,否则输出0
,生成二值掩膜常用于快速颜色分割cv2.bitwise_and(src1, src2, mask)
:对应像素做按位与操作,仅保留掩膜为255
的区域,实现掩膜与原图的叠加cv2.cvtColor(src, code)
:支持多种色彩空间转换,此处使用cv2.COLOR_BGR2HSV
将BGR
转为HSV
,以及cv2.COLOR_BGR2Lab / cv2.COLOR_Lab2BGR
在BGR
与Lab
之间变换cv2.createCLAHE(clipLimit, tileGridSize)
和clahe.apply(channel)
:创建CLAHE
对象并对单通道图像局部自适应均衡化,可避免全局均衡化导致的噪声过度放大。将均衡化后的L*
通道与原a
、b
通道合并,可在提升局部对比度的同时保留色彩信息np.hstack(tup)
:将多张形状相同的图像按水平方向拼接,用于同时展示多个处理结果,便于视觉对比
3. 颜色直方图分析与可视化
颜色直方图记录像素强度分布,是评估图像全局或局部对比度、亮度偏移及色彩偏差的基础工具,广泛应用于自动白平衡、阈值分割及风格迁移前的统计分析。在 Opencv
中 可以使用 cv2.calcHist
可对单通道或多通道图像分别计算直方图,并支持掩膜参数,只需将感兴趣区域的 mask
传入,即可实现局部区域的色彩分布可视化。
直方图均衡化 (cv2.equalizeHist
) 与自适应均衡化 (CLAHE
) 在灰度和 Lab L*
通道上效果显著,能动态拉伸分布至全量程,消除低对比度图像的暗部或高光溢出。也可以将直方图特征作为图像检索或机器学习模型的输入特征,实现基于颜色分布的图像检索、分类与风格识别。
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('1.jpeg')# 计算三个通道的直方图
colors = ('b', 'g', 'r')
for i, col in enumerate(colors):hist = cv2.calcHist([img], [i], None, [256], [0, 256])plt.plot(hist, label=f'{col.upper()} channel')plt.title('Color Histogram')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.legend()
plt.show()
关键代码解析:
cv2.calcHist(images, channels, mask, histSize, ranges)
:计算直方图,channels
指定通道索引,mask
控制分析区域
小结
本文系统的介绍了三种色彩空间的核心概念与 OpenCV
中的实现细节,并通过完整示例演示了实战中如何应用转换、分割与可视化技术。
系列链接
OpenCV计算机视觉实战(1)——计算机视觉简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)——计算机图像处理基础
OpenCV计算机视觉实战(4)——计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)——图像基础操作全解析
OpenCV计算机视觉实战(6)——经典计算机视觉算法
相关文章:

OpenCV计算机视觉实战(7)——色彩空间详解
OpenCV计算机视觉实战(7)——色彩空间详解 0. 前言1. RGB/BGR 色彩空间2. HSV / Lab 色彩空间3. 颜色直方图分析与可视化小结系列链接 0. 前言 本文深入探讨了三种常见色彩空间:RGB/BGR、HSV 与 CIELAB,并介绍了 OpenCV 中色彩空…...
体育直播网站如何实现实时数据
⚽ 你是否曾好奇: 当你在看足球直播时,进球瞬间比分立刻刷新;篮球比赛中,球员数据实时跳动……这些毫秒级的赛事数据,究竟是如何"飞"到你手机上的? 今天,我们就来扒一扒体育直播网站…...

【AI模型学习】上/下采样
文章目录 分割中的上/下采样下采样SegFormer和PVT(使用卷积)Swin-Unet(使用 Patch Merging) 上采样SegFormer(interpolate)Swin-Unet(Patch Expanding)逐级interpolate的方式反卷的方…...

Unity Shader入门(更新中)
参考书籍:UnityShader入门精要(冯乐乐著) 参考视频:Bilibili《Unity Shader 入门精要》 写在前面:前置知识需要一些计算机组成原理、线性代数、Unity的基础 这篇记录一些学历过程中的理解和笔记(更新中&…...

嵌入式学习的第二十六天-系统编程-文件IO+目录
一、文件IO相关函数 1.read/write cp #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include<unistd.h> #include<string.h>int main(int argc, char **argv) {if(argc<3){fprintf(stderr, …...

珠宝课程小程序源码介绍
这款珠宝课程小程序源码,基于ThinkPHPFastAdminUniApp开发,功能丰富且实用。ThinkPHP提供稳定高效的后台服务,保障数据安全与处理速度;FastAdmin助力快速搭建管理后台,提升开发效率;UniApp则让小程序能多端…...

KNN模型思想与实现
KNN算法简介 核心思想:通过样本在特征空间中k个最相似样本的多数类别来决定其类别归属。"附近的邻居确定你的属性"是核心逻辑 决策依据:采用"多数表决"原则,即统计k个最近邻样本中出现次数最多的类别 样本相似性度量 …...
【信息系统项目管理师】第15章:项目风险管理 - 55个经典题目及详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20题】【第…...

fscan教程1-存活主机探测与端口扫描
实验目的 本实验主要介绍fscan工具信息收集功能,对同一网段的主机进行存活探测以及常见服务扫描。 技能增长 通过本次实验的学习,了解信息收集的过程,掌握fscan工具主机探测和端口扫描功能。 预备知识 fscan工具有哪些作用? …...
蓝桥杯1447 砝码称重
问题描述 你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W1,W2,⋅⋅⋅,WN。 请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。 输入格式 输入的第一行包含一个整数 N。 第二行包含 N 个整数:W1,W2,W3,⋅⋅⋅,WN…...

腾讯2025年校招笔试真题手撕(三)
一、题目 今天正在进行赛车车队选拔,每一辆赛车都有一个不可以改变的速度。现在需要选取速度差距在10以内的车队(车队中速度的最大值减去最小值不大于10),用于迎宾。车队的选拔按照的是人越多越好的原则,给出n辆车的速…...

怎样通过神经网络估计股票走向
本博文将教会你如何通过神经网络建立股票模型并对其进行未来趋势估计,尽管博主已通过此方法取得一定利润,但是建议大家不要过分相信AI。本博文仅用于代码学习,请大家谨慎投资。 一、通过爬虫爬取股票往年数据 在信息爆炸的当今时代…...

【RocketMQ 生产者和消费者】- 生产者启动源码-上报生产者和消费者心跳信息到 broker(3)
文章目录 1. 前言2. sendHeartbeatToAllBrokerWithLock 上报心跳信息3. prepareHeartbeatData 准备心跳数据4. sendHearbeat 发送心跳上报请求5. broker 处理心跳请求5.1 heartBeat 处理心跳包5.2 createTopicInSendMessageBackMethod 创建重传 topic5.3 registerConsumer 注册…...

Python----循环神经网络(Word2Vec的优化)
一、负采样 基本思想: 在训练过程中,对于每个正样本(中心词和真实上下文词组成的词对),随机采样少量(如5-20个)负样本(中心词与非上下文词组成的词对)。 模型通过区分正…...

Simon J.D. Prince《Understanding Deep Learning》
学习神经网络和深度学习推荐这本书,这本书站位非常高,且很多问题都深入剖析了,甩其他同类书籍几条街。 多数书,不深度分析、没有知识体系,知识点零散、章节之间孤立。还有一些人Tian所谓的权威,醒醒吧。 …...

开搞:第四个微信小程序:图上县志
原因:我换了一个微信号来搞,因为用同一个用户,备案只能一个个的来。这样不行。所以我换了一个。原来注册过小程序。现在修改即可。注意做好计划后,速度备案和审核,不然你时间浪费不起。30元花起。 结构: -…...
模型评估与调优(PyTorch)
文章目录 模型评估方法混淆矩阵混淆矩阵中的指标ROC曲线(受试者工作特征)AUCR平方残差均方误差(MSE)均方根误差(RMSE)平均绝对误差(MAE) 模型调优方法交叉验证(CV&#x…...
sockaddr结构体详解
在网络编程中,sockaddr 结构体用于表示套接字的地址信息。由于不同协议(如 IPv4、IPv6、Unix 域套接字)的地址格式不同,实际使用中通常通过以下三种变体结构来处理不同类型的地址: 1. 通用地址结构:struct …...

Seata源码—7.Seata TCC模式的事务处理一
大纲 1.Seata TCC分布式事务案例配置 2.Seata TCC案例服务提供者启动分析 3.TwoPhaseBusinessAction注解扫描源码 4.Seata TCC案例分布式事务入口分析 5.TCC核心注解扫描与代理创建入口源码 6.TCC动态代理拦截器TccActionInterceptor 7.Action拦截处理器ActionIntercept…...

【语法】C++的map/set
目录 平衡二叉搜索树 set insert() find() erase() swap() map insert() 迭代器 erase() operator[] multiset和multimap 在之前学习的STL中,string,vector,list,deque,array都是序列式容器,它们的…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Live View Kit (3)
1.问题描述: 通过Push Kit创建实况窗之后,再更新实况窗失败,平台查询提示“实况窗端更新失败,通知未创建或已经过期”。 解决方案: 通过Push Kit更新实况窗内容的过程是自动更新的。客户端在创建本地实况窗后&#…...

vue vite textarea标签按下Shift+Enter 换行输入,只按Enter则提交的实现思路
注意input标签不能实现,需要用textarea标签 直接看代码 <template><textareav-model"message"keydown.enter"handleEnter"placeholder"ShiftEnter 换行,Enter 提交"></textarea> </template>&l…...
MySQL多线程备份工具mysqlpump详解!
MySQLPUMP备份工具详解 1. 概述 MySQLPump 是 MySQL 5.7 引入的一个客户端备份工具,用于替代传统的 mysqldump 工具。它提供了并行处理、进度状态显示、更好的压缩支持等新特性,能够更高效地执行 MySQL 数据库备份操作。 2. 主要特性 并行处理&#x…...
创建信任所有证书的HttpClient:Java 实现 HTTPS 接口调用,等效于curl -k
在 Java 生态中,HttpClient 和 Feign 都是调用第三方接口的常用工具,但它们的定位、设计理念和使用场景有显著差异。以下是详细对比: DIFF1. 定位与抽象层级 特性HttpClientFeign层级底层 HTTP 客户端库(处理原始请求/响应&#…...
Redisson分布式集合原理及应用
Redisson是一个用于Redis的Java客户端,它简化了复杂的数据结构和分布式服务的使用。 适用场景对比 数据结构适用场景优点RList消息队列、任务队列、历史记录分布式共享、阻塞操作、分页查询RMap缓存、配置中心、键值关联数据支持键值对、分布式事务、TTLRSet去重集…...

深入理解 PlaNet(Deep Planning Network):基于python从零实现
引言:基于模型的强化学习与潜在动态 基于模型的强化学习(Model-based Reinforcement Learning)旨在通过学习环境动态的模型来提高样本效率。这个模型可以用来进行规划,让智能体在不需要与真实环境进行每一次决策交互的情况下&…...
精益数据分析(75/126):用户反馈的科学解读与试验驱动迭代——Rally的双向验证方法论
精益数据分析(75/126):用户反馈的科学解读与试验驱动迭代——Rally的双向验证方法论 在创业的黏性阶段,用户反馈是优化产品的重要依据,但如何避免被表面反馈误导?如何将反馈转化为可落地的迭代策略&#x…...

仿腾讯会议——视频发送接收
1、 添加音频模块 2、刷新图片,触发重绘 3、 等比例缩放视频帧 4、 新建视频对象 5、在中介者内定义发送视频帧的函数 6、完成发送视频的函数 7、 完成开启/关闭视频 8、绑定视频的信号槽函数 9、 完成开启/关闭视频 10、 完成发送视频 11、 完成刷新图片显示 12、完…...

从3.7V/5V到7.4V,FP6291在应急供电智能门锁中的应用
在智能家居蓬勃发展的当下,智能门锁以其便捷、安全的特性,成为现代家庭安防的重要组成部分。在智能门锁电量耗尽的情况下,应急电源外接移动电源(USB5V输入) FP6291升压到7.4V供电可应急开锁。增强用户在锁具的安全性、…...
java后端-海外登录(谷歌/FaceBook)
前言 由于最近公司的项目要在海外运行,因此需要对接海外的登录,目前就是谷歌和facebook两种,后面支付也是需要的,后续再进行书写 谷歌登录 这个相对比较容易,而且只提供给安卓即可,废话就不多说了,直接贴解决方案 引入maven依赖 <dependency> <groupId>com.go…...