9.5HSV体系进行颜色分割

news2024/11/16 6:23:43

基本概念

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2160105.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AOT源码解析4.1-model主体解析

1 输入数据 VOS的数据集处理操作可见数据集操作&#xff0c;这里是进行数据集提取完毕后的操作。 图2&#xff1a;如图所示&#xff0c;使用datasets提取出数据之后&#xff0c;在模型训练阶段对数据做图中操作。即&#xff1a;将batch_size大小的ref_imgs、prev_imgs&#x…

【JavaEE】——线程“饿死问题” wait notify

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 引子&#xff1a; 一&#xff1a;情景引入 二&#xff1a;线程饿死问题 1&#xff1a;线程饿死 2&a…

24 C 语言常用的字符串处理函数详解:strlen、strcat、strcpy、strcmp、strchr、strrchr、strstr、strtok

目录 1 strlen 1.1 函数原型 1.2 功能说明 1.3 案例演示 1.4 注意事项 2 strcat 2.1 函数原型 2.2 功能说明 2.3 案例演示 2.4 注意事项 3 strcpy 3.1 函数原型 3.2 功能说明 3.3 案例演示 3.4 注意事项 4 strcmp 4.1 函数原型 4.2 功能说明 4.3 案例演示 …

在 VS Code 中调试 C++ 项目

选择调试器环境 从预定义的调试配置中进行选择&#xff0c;生成预定义launch.json文件,可能是空模板 {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft…

Qwen2-VL全面解读!阿里开源多模态视觉语言模型,多项超越GPT4o与Claude 3.5-Sonnet

文章链接&#xff1a;https://arxiv.org/pdf/2409.12191 Github链接&#xff1a;https://github.com/QwenLM/Qwen2-VL 亮点直击 本文介绍了Qwen系列大型视觉语言模型的最新成员&#xff1a;Qwen2-VL系列&#xff0c;该系列包括三款开放权重模型&#xff0c;总参数量分别为20亿、…

QString 构建SQL语句可以往数据库中添加“\n“字符串

网上找了很多案例关于怎么样能在Mysql数据库中插入带\n的字符串&#xff0c;如图&#xff1a; 本以为很容易的一件事&#xff0c;没想到思考了半天&#xff0c;在这里记录一下&#xff0c;以为\n是转义字符的原因&#xff0c;所以并不是我想的那么简单。网上有用R&#xff08;“…

力扣 困难 154.寻找旋转排序数组中的最小值 II

文章目录 题目介绍题解 题目介绍 题解 题源&#xff1a; 153.寻找旋转排序数组中的最小值 在此基础上&#xff0c;进行二分之前&#xff0c;单独处理一下左指针和最后一个数相同的情况就好了。 class Solution {public int findMin(int[] nums) {int left 0, right nums.le…

使用豆包Marscode 创建了一个”天气预报“小应用

以下是「豆包MarsCode 体验官」优秀文章&#xff0c;作者一拳干爆显示器。 前言 本文介绍了我第一次使用我在MarsCode IDE制作了一款天气预报的应用 其中在正文的头部以及结语部分发表了我在MarsCode编程中的体验情况&#xff0c;而正文的中间主要是我项目制作的细节步骤 豆…

【自动驾驶】基于车辆几何模型的横向控制算法 | Pure Pursuit 纯跟踪算法详解与编程实现

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

Face++API调用

人脸检测API调用 import requests import json #将自己的KEY和Secret进行替换 API_KEYyour_API_KET API_SECRETyour_API_Secret# 人脸识别的URL URL https://api-cn.faceplusplus.com/facepp/v3/detect# 请求参数,需要什么参数传入什么参数 data {"api_key":API…

力扣2208.将数组各元素总和减半需要最少次数(贪心+堆)

题目描述 给你一个正整数数组 nums 。每一次操作中&#xff0c;你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。&#xff08;注意&#xff0c;在后续操作中你可以对减半过的数继续执行操作&#xff09;请你返回将 nums 数组和 至少 减少一半的 最少 操作数。 示例…

零基础入门AI大模型应用开发——第三天:使用python实现问答机器人

一、简介 问答机器人是一种能够理解用户提问并提供相关答案的程序。它可以用于各种场景&#xff0c;如客户支持、在线教育、信息检索等。用户通过自然语言输入问题&#xff0c;机器人则通过分析问题并检索相关信息来提供回答。 使用什么技术实现的&#xff1f; 自然语言处理&…

Leetcode 合并区间

我们借助一个辅助链表(元素类型是一维数组)来进行结果统计。 这个算法解决了“合并区间”的问题&#xff0c;具体要求是给定一组区间&#xff08;每个区间有开始和结束位置&#xff09;&#xff0c;如果两个区间有重叠&#xff0c;那么需要将它们合并成一个区间&#xff0c;并…

【Linux】ubuntu 16.04 搭建jdk 11 环境(亲测可用)

目录 0.环境 1.题外话 2.详细 0.环境 windows11 主机 Virtual Box 7.0 ubuntu 16.04系统 想搭建个 jdk11的环境&#xff0c;用于项目 1.题外话 因为虚拟机与主机传输文件不方便&#xff0c;所以可以尝试用共享文件夹的方式传输&#xff0c;亲测可用&#xff0c;参考以下博…

JAVA并发编程系列(10)Condition条件队列-并发协作者

一线大厂面试真题&#xff0c;模拟消费者-生产者场景。 同样今天的分享&#xff0c;我们不纸上谈兵&#xff0c;也不空谈八股文。以实际面经、工作实战经验进行开题&#xff0c;然后再剖析核心源码原理。 按常见面经要求&#xff0c;生产者生产完指定数量产品后&#xff0c;才能…

计算机毕业设计 校运会管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

函数模板进阶 - 为什么函数模板不要特化?

本文参考文章2001 年 7 月的 C/C++ Users Journal,第 19 卷第 7 期:Why Not Specialize Function Templates? 大家有兴趣可以看看原文。 文章目录 一、 重载和特化1. 重载2. 特化二、特化和重载的调用优先级1. 第一份代码2. 第二份代码3. 原因三、函数模板特化的书写格式1. …

防护装备穿戴与否检测系统源码分享

防护装备穿戴与否检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comp…

【机器学习】生成对抗网络(GAN)——生成新数据的神经网络

生成对抗网络&#xff08;Generative Adversarial Networks&#xff0c;简称GAN&#xff09;是一种创新的神经网络结构&#xff0c;近年来在机器学习和人工智能领域引起了广泛的关注。GAN的核心思想是通过两个神经网络的对抗性训练&#xff0c;生成高质量的、与真实数据相似的新…

webview2加载本地页面

加载方式 通过导航到文件 URL 加载本地内容 使用方式&#xff1a; webView->Navigate( L"file:///C:/Users/username/Documents/GitHub/Demos/demo-to-do/index.html"); 但是这种方式存在一些问题&#xff0c;比如&#xff1a; 存在跨域问题&#xff08;我加载…