opencv RGB与HSV转化

HSV和RGB都是表示色彩的方式。H为色相,S为饱和度,V为明度,RGB代表红绿蓝三种颜色分量。
色相:用0-360度表示颜色。
在这里插入图片描述
饱和度:色彩纯度,越低颜色越暗淡,范围0~1。
明度:色彩明暗度,越高越亮越接近白色,越低越暗越接近黑色,范围0~1。

转化公式如下:
从RGB到HSV
在这里插入图片描述
从HSV到RGB
在这里插入图片描述
RGB和HSV按照公式进行转化,但是要注意r,g,b的范围要从0255变成01参与计算,最后的结果,HSV为float类型,RGB为uchar类型要互相转化。

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <math.h>

cv::Mat BGR2HSV(cv::Mat img) {
	int width = img.cols;
	int height = img.rows;

	float r, g, b;
	float h, s, v;
	float _max, _min;

	cv::Mat hsv = cv::Mat::zeros(height, width, CV_32FC3);//32位浮点数三通道

	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			//r g b变为0~1范围
			r = (float)img.at<cv::Vec3b>(y, x)[2] / 255;
			g = (float)img.at<cv::Vec3b>(y, x)[1] / 255;
			b = (float)img.at<cv::Vec3b>(y, x)[0] / 255;

			_max = fmax(r, fmax(g, b));
			_min = fmin(r, fmin(g, b));

			
			if (_max == _min) {
				h = 0;
			}
			else if (_min == b) {
				h = 60 * (g - r) / (_max - _min) + 60;
			}
			else if (_min == r) {
				h = 60 * (b - g) / (_max - _min) + 180;
			}
			else if (_min == g) {
				h = 60 * (r - b) / (_max - _min) + 300;
			}

			s = _max - _min;
			v = _max;

			hsv.at<cv::Vec3f>(y, x)[0] = h;
			hsv.at<cv::Vec3f>(y, x)[1] = s;
			hsv.at<cv::Vec3f>(y, x)[2] = v;
		}
	}
	return hsv;
}

// 将RGB的uchar转为HSV的float
cv::Mat HSV2BGR(cv::Mat hsv) {
	int width = hsv.cols;
	int height = hsv.rows;

	float h, s, v;
	double c, _h, _x;
	double r, g, b;

	cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3);

	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {

			h = hsv.at<cv::Vec3f>(y, x)[0];
			s = hsv.at<cv::Vec3f>(y, x)[1];
			v = hsv.at<cv::Vec3f>(y, x)[2];

			c = s;
			_h = h / 60;
			_x = c * (1 - abs(fmod(_h, 2) - 1));

			r = g = b = v - c;

			if (_h < 1) {
				r += c;
				g += _x;
			}
			else if (_h < 2) {
				r += _x;
				g += c;
			}
			else if (_h < 3) {
				g += c;
				b += _x;
			}
			else if (_h < 4) {
				g += _x;
				b += c;
			}
			else if (_h < 5) {
				r += _x;
				b += c;
			}
			else if (_h < 6) {
				r += c;
				b += _x;
			}
			//*255 并变成uchar类型
			out.at<cv::Vec3b>(y, x)[0] = (uchar)(b * 255);
			out.at<cv::Vec3b>(y, x)[1] = (uchar)(g * 255);
			out.at<cv::Vec3b>(y, x)[2] = (uchar)(r * 255);
		}
	}
	return out;
}


cv::Mat inverse_hue(cv::Mat hsv) {
	int height = hsv.rows;
	int width = hsv.cols;

	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			//Vec3f可以看作是vector<float, 3> 即float类型的,长度为3的vector向量
			//HSV三个分量的表示均为浮点数
			hsv.at<cv::Vec3f>(y, x)[0] = fmod(hsv.at<cv::Vec3f>(y, x)[0] + 180, 360);//fmod对360度取余
		}
	}

	return hsv;
}


int main(int argc, const char* argv[]) {
	cv::Mat img = cv::imread("C:/Users/zxdn/Desktop/boy.jpg", cv::IMREAD_COLOR);

	cv::Mat hsv = BGR2HSV(img);
	hsv = inverse_hue(hsv);//色相反转
	cv::Mat out = HSV2BGR(hsv);
	cv::imshow("原图", img);
	cv::imshow("色相反转180度", out);
	cv::waitKey(0);
	cv::destroyAllWindows();

	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值