9.5HSV体系进行颜色分割

基本概念

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;
}

运行结果3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值