OpenCV 中使用 inRange 进行 HSV 阈值操作
基于 OpenCV 的 HSV 色彩空间阈值操作方法。内容涵盖 HSV 与 RGB 的区别、inRange 函数原理、C++ 代码实现及详细解析。通过视频捕获、颜色空间转换、动态阈值调整及结果显示,实现了实时的颜色对象检测。文章修正了原有代码错误,补充了环境配置、回调逻辑说明及常见问题优化建议,适用于计算机视觉初学者进行颜色分割实践。

基于 OpenCV 的 HSV 色彩空间阈值操作方法。内容涵盖 HSV 与 RGB 的区别、inRange 函数原理、C++ 代码实现及详细解析。通过视频捕获、颜色空间转换、动态阈值调整及结果显示,实现了实时的颜色对象检测。文章修正了原有代码错误,补充了环境配置、回调逻辑说明及常见问题优化建议,适用于计算机视觉初学者进行颜色分割实践。

在本教程中,您将学习如何:
RGB 颜色模型是计算机显示图像的基础,它通过红(Red)、绿(Green)、蓝(Blue)三个通道的组合来表示颜色。然而,RGB 模型并不符合人类对颜色的直观感知方式。例如,改变亮度可能会同时影响所有通道,导致难以单独调整颜色的明暗而不改变其色相。
HSV(Hue, Saturation, Value)色彩空间将颜色信息分解为三个独立的维度:
由于色调通道专门用于建模颜色类型,因此在需要根据颜色分割对象的图像处理任务中,HSV 空间比 RGB 更加有效和稳定。例如,在光照条件变化时,HSV 的色调分量通常比 RGB 的通道更稳定。
inRange 是 OpenCV 提供的一个核心函数,用于检查数组元素是否位于给定的下限和上限之间。在图像处理中,它常用于创建掩膜(Mask),即生成一个二值图像,其中满足条件的像素值为白色(255),不满足条件的像素值为黑色(0)。
基本语法如下:
cv::inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst);
src: 输入图像。lowerb: 下界数组。upperb: 上界数组。dst: 输出掩膜图像。该函数支持多通道数组,对于单通道图像,它比较每个像素值是否在范围内;对于多通道图像(如 BGR 或 HSV),它会逐通道进行比较。
在开始编写代码之前,请确保您的开发环境已安装 OpenCV 库。如果您使用的是 C++,通常需要配置 CMake 或 IDE 以链接 OpenCV 库文件。此外,您需要一个摄像头设备来实时捕获视频流进行测试。
以下是一个完整的 C++ 示例程序,展示了如何使用 VideoCapture 捕获视频,将其转换为 HSV 格式,并利用 inRange 函数结合滑动条(Trackbar)动态调整 HSV 阈值范围。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// 定义 HSV 的最大值
const int max_value_H = 360 / 2; // OpenCV 中 H 的范围通常是 0-179
const int max_value_S = 255;
const int max_value_V = 255;
const string window_capture_name = "视频捕获";
const string window_detection_name = "对象检测";
// 全局变量存储当前阈值范围
int low_H = 0, low_S = 0, low_V = 0;
int high_H = max_value_H, high_S = max_value_S, high_V = max_value_V;
// 回调函数:低 H 阈值跟踪栏
static void on_low_H_thresh_trackbar(int, void*) {
low_H = min(low_H + 1, high_H - 1);
setTrackbarPos("低 H", window_detection_name, low_H);
}
// 回调函数:高 H 阈值跟踪栏
static void on_high_H_thresh_trackbar(int, void*) {
high_H = max(high_H - 1, low_H + 1);
setTrackbarPos("高 H", window_detection_name, high_H);
}
// 回调函数:低 S 阈值跟踪栏
static void on_low_S_thresh_trackbar(int, void*) {
low_S = min(low_S + 1, high_S - 1);
setTrackbarPos("低 S", window_detection_name, low_S);
}
// 回调函数:高 S 阈值跟踪栏
static void on_high_S_thresh_trackbar(int, void*) {
high_S = max(high_S - 1, low_S + 1);
setTrackbarPos("高 S", window_detection_name, high_S);
}
// 回调函数:低 V 阈值跟踪栏
static void on_low_V_thresh_trackbar(int, void*) {
low_V = min(low_V + 1, high_V - 1);
setTrackbarPos("低 V", window_detection_name, low_V);
}
// 回调函数:高 V 阈值跟踪栏
static void on_high_V_thresh_trackbar(int, void*) {
high_V = max(high_V - 1, low_V + 1);
setTrackbarPos("高 V", window_detection_name, high_V);
}
int main(int argc, char** argv) {
// 初始化视频捕获对象
VideoCapture cap(argc > 1 ? atoi(argv[1]) : 0);
if (!cap.isOpened()) {
cerr << "无法打开摄像头" << endl;
return -1;
}
// 创建窗口
namedWindow(window_capture_name, WINDOW_AUTOSIZE);
namedWindow(window_detection_name, WINDOW_AUTOSIZE);
// 创建跟踪栏以设置 HSV 值的范围
createTrackbar("低 H", window_detection_name, &low_H, max_value_H, on_low_H_thresh_trackbar);
createTrackbar("高 H", window_detection_name, &high_H, max_value_H, on_high_H_thresh_trackbar);
createTrackbar("低 S", window_detection_name, &low_S, max_value_S, on_low_S_thresh_trackbar);
createTrackbar("高 S", window_detection_name, &high_S, max_value_S, on_high_S_thresh_trackbar);
createTrackbar("低 V", window_detection_name, &low_V, max_value_V, on_low_V_thresh_trackbar);
createTrackbar("高 V", window_detection_name, &high_V, max_value_V, on_high_V_thresh_trackbar);
Mat frame, frame_HSV, frame_threshold;
while (true) {
cap >> frame;
if (frame.empty()) {
break;
}
// 从 BGR 转换到 HSV 色彩空间
cvtColor(frame, frame_HSV, COLOR_BGR2HSV);
// 根据 HSV 范围值检测对象
inRange(frame_HSV, Scalar(low_H, low_S, low_V), Scalar(high_H, high_S, high_V), frame_threshold);
// 显示原始框架
imshow(window_capture_name, frame);
// 显示处理后的阈值框架
imshow(window_detection_name, frame_threshold);
// 等待按键退出
char key = (char)waitKey(30);
if (key == 'q' || key == 27) {
break;
}
}
return 0;
}
程序首先尝试打开默认摄像头(索引 0)。如果命令行参数提供了设备索引,则优先使用提供的索引。随后创建两个窗口,分别用于显示原始视频流和处理后的二值掩膜。
为了确保阈值的有效性,回调函数中加入了边界检查逻辑。例如,当调整'低 H'时,必须保证它小于'高 H',反之亦然。这避免了因用户误操作导致范围无效(如下限大于上限)的情况。
cvtColor 函数将输入的 BGR 图像转换为 HSV 格式。这是关键步骤,因为 inRange 在 HSV 空间中能更准确地分离特定颜色的物体,尤其是在光照变化较大的环境下。
inRange 函数接收转换后的图像和当前的 HSV 范围,生成一个二值图像。白色区域代表匹配的颜色,黑色区域代表背景。最后通过 imshow 展示结果,并通过 waitKey 监听键盘输入以控制程序生命周期。
如果检测到的物体不完整或有噪点,可以通过调整跟踪栏微调 HSV 范围。通常先固定 S 和 V,调整 H 找到色相范围,再逐步调整饱和度和明度。
对于高分辨率视频流,实时处理可能会有延迟。可以考虑降低视频分辨率或使用多线程处理,或者仅处理感兴趣区域(ROI)。
HSV 虽然比 RGB 更稳定,但在极端光照条件下仍可能失效。在实际应用中,可以结合自适应阈值算法或增加预处理步骤(如直方图均衡化)来提高鲁棒性。
本教程详细介绍了如何在 OpenCV 中使用 inRange 函数配合 HSV 色彩空间进行颜色阈值操作。通过动态调整跟踪栏,用户可以实时观察不同颜色范围对检测结果的影响。掌握这一技术是进行高级计算机视觉任务(如物体追踪、手势识别等)的基础。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online