基本概念
inRange() 函数是 OpenCV 中用于图像处理的一个非常有用的函数,即从图像中提取出介于指定范围内的像素值。这个函数在图像处理中特别有用,比如颜色检测、背景去除等应用。它主要用于图像的阈值处理,但与其他阈值方法(如 threshold())不同的是,inRange() 可以设定一个范围来过滤像素值,非常适合用于色彩空间的分割,如从视频或图像中分离出特定颜色的物体。该函数经常与 HSV 色彩空间结合使用,因为 HSV 色彩空间对颜色变化的反应更加直观和自然。
函数原型
在 OpenCV 中,inRange() 函数的原型如下:
void cv::inRange(InputArray src, InputArray lowerb,
InputArray upperb, OutputArray dst)
参数介绍:
src: 输入图像,通常是一个多通道数组(图像)。
lowerb: 数组元素的下界,包含与 src 相同数量的通道。
upperb: 数组元素的上界,同样包含与 src 相同数量的通道。
dst: 输出图像,与 src 尺寸和类型相同。对于 src 中的每个像素,如果其值在 lowerb 和 upperb 之间(包括这两个边界),则 dst 中的相应像素设置为 255(白色),否则设置为 0(黑色)。
使用示例
假设你想从一幅图像中分离出绿色的物体。一种常用的方法是将图像从 BGR 色彩空间转换到 HSV 色彩空间,然后使用 inRange() 函数根据 HSV 值范围来分割绿色。
步骤
1.读取图像:使用 cv::imread() 读取图像。
2.转换色彩空间:使用 cv::cvtColor() 将图像从 BGR 转换到 HSV。
3.定义颜色范围:在 HSV 色彩空间中定义绿色的上下界。
4.应用 inRange():使用 inRange() 函数分割出绿色区域。
5.显示结果:显示原始图像和分割后的图像。
示例代码1
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//
int main()
{
// 读取图像
Mat img = imread("98.png");
if (img.empty())
{
std::cout << "Could not read the image." << std::endl;
return 1;
}
// 转换到 HSV
Mat hsv;
cvtColor(img, hsv, COLOR_BGR2HSV);
// 定义绿色的 HSV 范围
// 注意:这些值可能需要根据实际图像进行调整
Scalar lower_green(25, 36, 25); // 较低的绿色
Scalar upper_green(255, 70, 255); // 较高的绿色
// 创建一个掩模
Mat mask;
inRange(hsv, lower_green, upper_green, mask);
// 使用掩模
Mat result;
bitwise_and(img, img, result, mask);
// 显示结果
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
namedWindow("Green Objects", WINDOW_NORMAL);
imshow("Green Objects", result);
waitKey(0);
return 0;
}
//注意:HSV 中的绿色范围(本例中的 lower_green 和 upper_green)可能需要根据你的特定应用场景进行调整。
//不同的光照条件和相机设置可能会影响图像中的 HSV 值。
运行结果1
红色分量
下面是一个使用 C++ 和 OpenCV 的 inRange() 函数的基本示例,以说明如何使用它来提取图像中的特定颜色:
1.导入必要的头文件:
#include <opencv2/opencv.hpp>
using namespace cv;
2.加载图像:
Mat src = imread("path/to/your/image.jpg");
if (src.empty()) {
std::cout << "Could not open or find the image" << std::endl;
return -1;
}
3.转换到HSV颜色空间:
在许多情况下,HSV 颜色模型比 RGB 更适合进行颜色分割,
因为颜色的属性(色调、饱和度、亮度)更清晰地分离了。
Mat hsv;
cvtColor(src, hsv, COLOR_BGR2HSV);
4.定义阈值:
假设我们要选择特定的颜色范围,例如红色。我们需要定义两个向量来存储HSV颜色空间的下限和上限。
Scalar lower_red = {160, 100, 100}; // 这些值取决于你要选择的颜色
Scalar upper_red = {180, 255, 255};
5.应用 inRange() 函数:
使用 inRange() 函数将图像像素与指定的阈值进行比较,并创建一个掩码,其中介于这两个阈值之间的像素值设置为白色(255),其余设置为黑色(0)。
Mat mask;
inRange(hsv, lower_red, upper_red, mask);
6.显示结果:
显示原始图像和掩码图像以便对比查看效果。
namedWindow("Original Image", WINDOW_AUTOSIZE);
imshow("Original Image", src);
namedWindow("Mask", WINDOW_AUTOSIZE);
imshow("Mask", mask);
7.等待按键退出:
waitKey(0); // Wait for a keystroke in the window
8.清理:
不要忘记释放所有使用的内存资源。
destroyAllWindows();
以上步骤展示了如何使用 inRange() 函数来创建一个简单的颜色识别程序。
请注意,实际的颜色阈值可能需要根据具体的应用场景和光照条件进行调整。
完整代码2
#include "pch.h"
//1.导入必要的头文件:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//2.加载图像:
int main()
{
Mat src = imread("58.jpeg");
if (src.empty())
{
std::cout << "Could not open or find the image" << std::endl;
return -1;
}
//3.转换到HSV颜色空间:
//在许多情况下,HSV 颜色模型比 RGB 更适合进行颜色分割,
//因为颜色的属性(色调、饱和度、亮度)更清晰地分离了。
Mat hsv;
cvtColor(src, hsv, COLOR_BGR2HSV);
//4.定义阈值:
//假设我们要选择特定的颜色范围,例如红色。我们需要定义两个向量来存储HSV颜色空间的下限和上限。
Scalar lower_red = { 160, 100, 100 }; // 这些值取决于你要选择的颜色
Scalar upper_red = { 180, 255, 255 };
//5.应用 inRange() 函数:
//使用 inRange() 函数将图像像素与指定的阈值进行比较,并创建一个掩码,其中介于这两个阈值之间的像素值设置为白色(255),其余设置为黑色(0)。
Mat mask;
inRange(hsv, lower_red, upper_red, mask);
//6.显示结果:
//显示原始图像和掩码图像以便对比查看效果。
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", src);
namedWindow("Mask", WINDOW_NORMAL);
imshow("Mask", mask);
//7.等待按键退出:
waitKey(0); // Wait for a keystroke in the window
//8.清理:
//不要忘记释放所有使用的内存资源。
destroyAllWindows();
return 0;
//以上步骤展示了如何使用 inRange() 函数来创建一个简单的颜色识别程序。
//请注意,实际的颜色阈值可能需要根据具体的应用场景和光照条件进行调整。
}
运行结果2
实验代码3
#include "pch.h"
//#pragma comment(lib, "opencv_world450d.lib")
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <opencv2/imgproc/types_c.h>
#include <iostream>
using namespace std;
using namespace cv;
//输入图像
Mat img;
//灰度值归一化
Mat bgr;
//HSV图像
Mat hsv;
//色相
int hmin = 0;
int hmin_Max = 360;
int hmax = 180;
int hmax_Max = 180;
//饱和度
int smin = 0;
int smin_Max = 255;
int smax = 255;
int smax_Max = 255;
//亮度
int vmin = 106;
int vmin_Max = 255;
int vmax = 255;
int vmax_Max = 255;
//显示原图的窗口
string windowName = "src";
//输出图像的显示窗口
string dstName = "dst";
//输出图像
Mat dst;
//回调函数
void callBack(int, void*)
{
//输出图像分配内存
dst = Mat::zeros(img.size(), img.type());
//掩码
Mat mask;
inRange(hsv, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), mask);
//掩模到原图的转换
for (int r = 0; r < bgr.rows; r++)
{
for (int c = 0; c < bgr.cols; c++)
{
if (mask.at<uchar>(r, c) == 255)
{
dst.at<Vec3b>(r, c) = bgr.at<Vec3b>(r, c);
}
}
}
//输出图像
imshow(dstName, dst);
//保存图像
//dst.convertTo(dst, CV_8UC3, 255.0, 0);
imwrite("HSV_inRange.jpg", dst);
}
int main(int argc, char** argv)
{
//输入图像
img = imread("SBB.jpg");
if (!img.data || img.channels() != 3)
return -1;
imshow(windowName, img);
bgr = img.clone();
//颜色空间转换
cvtColor(bgr, hsv, CV_BGR2HSV);
//cout << hsv << endl;
//定义输出图像的显示窗口
//namedWindow(dstName, WINDOW_GUI_EXPANDED);
namedWindow(dstName, WINDOW_NORMAL);
//调节色相 H
createTrackbar("hmin", dstName, &hmin, hmin_Max, callBack);
createTrackbar("hmax", dstName, &hmax, hmax_Max, callBack);
//调节饱和度 S
createTrackbar("smin", dstName, &smin, smin_Max, callBack);
createTrackbar("smax", dstName, &smax, smax_Max, callBack);
//调节亮度 V
createTrackbar("vmin", dstName, &vmin, vmin_Max, callBack);
createTrackbar("vmax", dstName, &vmax, vmax_Max, callBack);
callBack(0, 0);
waitKey(0);
return 0;
}