OpenCV 中使用 inRange 进行 HSV 阈值操作
目标
在本教程中,您将学习如何:
- 使用 OpenCV 函数执行基本的阈值操作。
- 根据 HSV 色彩空间中的像素值范围检测对象。
- 理解颜色分割在图像处理中的基本原理。
理论背景
为什么使用 HSV 色彩空间?
RGB 颜色模型是计算机显示图像的基础,它通过红(Red)、绿(Green)、蓝(Blue)三个通道的组合来表示颜色。然而,RGB 模型并不符合人类对颜色的直观感知方式。例如,改变亮度可能会同时影响所有通道,导致难以单独调整颜色的明暗而不改变其色相。
HSV(Hue, Saturation, Value)色彩空间将颜色信息分解为三个独立的维度:
- 色调 (Hue):表示颜色的种类,如红色、绿色或蓝色。通常用角度(0-360 度)表示。
- 饱和度 (Saturation):表示颜色的纯度或强度。从灰色(不饱和)到完全鲜艳的颜色。
- 明度 (Value):表示颜色的亮度或强度。从黑色到最亮的颜色。
由于色调通道专门用于建模颜色类型,因此在需要根据颜色分割对象的图像处理任务中,HSV 空间比 RGB 更加有效和稳定。例如,在光照条件变化时,HSV 的色调分量通常比 RGB 的通道更稳定。
inRange 函数原理
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 / ;
max_value_S = ;
max_value_V = ;
string window_capture_name = ;
string window_detection_name = ;
low_H = , low_S = , low_V = ;
high_H = max_value_H, high_S = max_value_S, high_V = max_value_V;
{
low_H = (low_H + , high_H - );
(, window_detection_name, low_H);
}
{
high_H = (high_H - , low_H + );
(, window_detection_name, high_H);
}
{
low_S = (low_S + , high_S - );
(, window_detection_name, low_S);
}
{
high_S = (high_S - , low_S + );
(, window_detection_name, high_S);
}
{
low_V = (low_V + , high_V - );
(, window_detection_name, low_V);
}
{
high_V = (high_V - , low_V + );
(, window_detection_name, high_V);
}
{
;
(!cap.()) {
cerr << << endl;
;
}
(window_capture_name, WINDOW_AUTOSIZE);
(window_detection_name, WINDOW_AUTOSIZE);
(, window_detection_name, &low_H, max_value_H, on_low_H_thresh_trackbar);
(, window_detection_name, &high_H, max_value_H, on_high_H_thresh_trackbar);
(, window_detection_name, &low_S, max_value_S, on_low_S_thresh_trackbar);
(, window_detection_name, &high_S, max_value_S, on_high_S_thresh_trackbar);
(, window_detection_name, &low_V, max_value_V, on_low_V_thresh_trackbar);
(, window_detection_name, &high_V, max_value_V, on_high_V_thresh_trackbar);
Mat frame, frame_HSV, frame_threshold;
() {
cap >> frame;
(frame.()) {
;
}
(frame, frame_HSV, COLOR_BGR2HSV);
(frame_HSV, (low_H, low_S, low_V), (high_H, high_S, high_V), frame_threshold);
(window_capture_name, frame);
(window_detection_name, frame_threshold);
key = ()();
(key == || key == ) {
;
}
}
;
}


