C++ RGB格式转换为HSV格式,颜色提取操作

简介

颜色的提取在HSV空间效果更好,然而我们的图像格式一般都是RGB格式的。因此我们首先需要用到将RGB图像格式转换为HSV格式。简单介绍一下HSV,H表示色彩、色调,S表示纯度,V表示色彩的明亮程度。值得一提的是,HSV各数据的取值范围根据各自的计算方法都没统一。
在这里插入图片描述

公式:

设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数
设 max 等于 r, g, b 中的最大者
设 min 等于 r, g, b 中的最小者
在这里插入图片描述

代码(BGR转HSV):

我们采用的方法,H取值范围[0,360],S取值范围[0,1],V取值范围[0,1]

struct BGR	// 定义BGR结构体
{
	uchar b;
	uchar g;
	uchar r;
};
struct HSV // 定义HSV结构体
{
	int h;
	double s;
	double v;
};

bool IsEquals(double val1, double val2)
{
	return fabs(val1 - val2) < 0.001;
}

// 将RGB格式转换为HSV格式
void BGR2HSV(BGR &bgr, HSV &hsv)	
{
	double b, g, r;
	double h, s, v;
	double min, max;
	double delta;

	b = bgr.b / 255.0;
	g = bgr.g / 255.0;
	r = bgr.r / 255.0;

	if (r > g)
	{
		max = MAX(r, b);
		min = MIN(g, b);
	}
	else
	{
		max = MAX(g, b);
		min = MIN(r, b);
	}

	v = max;
	delta = max - min;

	if (IsEquals(max, 0))
		s = 0.0;
	else
		s = delta / max;

	if (max == min)
		h = 0.0;
	else
	{
		if (IsEquals(r, max) && g >= b)
		{
			h = 60 * (g - b) / delta + 0;
		}
		else if (IsEquals(r, max) && g < b)
		{
			h = 60 * (g - b) / delta + 360;
		}
		else if (IsEquals(g, max))
		{
			h = 60 * (b - r) / delta + 120;
		}
		else if (IsEquals(b, max))
		{
			h = 60 * (r - g) / delta + 240;
		}
	}

	hsv.h = (int)(h + 0.5);
	hsv.h = (hsv.h > 359) ? (hsv.h - 360) : hsv.h;
	hsv.h = (hsv.h < 0) ? (hsv.h + 360) : hsv.h;
	hsv.s = s;
	hsv.v = v;
}


// 调用
int main()
{
	''''''
	// 载入检测图片
	Mat srcImg = imread("./src/3.jpg");
	int width = srcImg.cols;//图像宽度  
	int height = srcImg.rows;//图像高度


	Mat matRgb = Mat::zeros(srcImg.size(), CV_8UC1);
	int x, y; //循环  
	for (y = 0; y < height; y++)
		for (x = 0; x < width; x++)
		{
			// 获取BGR值  
			BGR bgr;
			bgr.b = srcImg.at<Vec3b>(y, x)[0];
			bgr.g = srcImg.at<Vec3b>(y, x)[1];
			bgr.r = srcImg.at<Vec3b>(y, x)[2];

			HSV hsv;
			BGR2HSV(bgr, hsv); // bgr转hsv
}

根据hsv分量模型,各种颜色范围分布如下:
注:该表的数值范围:H[0,180],S[0,255],v[0,255]
而之前代码获取的数值范围:H[0,360],S[0,1],v[0,1]
因此需要进行一个转换.

在这里插入图片描述

代码(提取红色区域)

	// 第一步:分割红色颜色色块
	Mat matRgb = Mat::zeros(srcImg.size(), CV_8UC1);
	int x, y; //循环  
	for (y = 0; y < height; y++)
		for (x = 0; x < width; x++)
		{
			// 获取BGR值  
			BGR bgr;
			bgr.b = srcImg.at<Vec3b>(y, x)[0];
			bgr.g = srcImg.at<Vec3b>(y, x)[1];
			bgr.r = srcImg.at<Vec3b>(y, x)[2];

			HSV hsv;
			BGR2HSV(bgr, hsv); // bgr转hsv
			//红色范围  
			if ((hsv.h >= 156* 2 && hsv.h <= 180 * 2 || hsv.h >= 0 && hsv.h <= 10 * 2) 
				&& hsv.s * 255 >= 43&& hsv.s * 255 <= 255 
				&& hsv.v * 255 >= 46 && hsv.v * 255 <= 255)
			{
				matRgb.at<uchar>(y, x) = 255;
			}// if
		}// for

参考博客:
https://blog.csdn.net/greenapple_shan/article/details/40214719
https://blog.csdn.net/weixin_39128119/article/details/88669521
https://www.cnblogs.com/wangyblzu/p/5710715.html
https://blog.csdn.net/lly_3485390095/article/details/104570885

  • 3
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值