从RGB 到 HSV 的转换详细介绍

1.RGB

RGB是从颜色发光的原理来设计定的,通俗点说它的颜色混合方式就好像有红、绿、蓝三盏灯,当它们的光相互叠合的时候,色彩相混,而亮度却等于两者亮度之总和,越混合亮度越高,即加法混合。

红、绿、蓝三个颜色通道每种色各分为256阶亮度,在0时“灯”最弱——是关掉的,而在255时“灯”最亮。当三色灰度数值相同时,产生不同灰度值的灰色调,即三色灰度都为0时,是最暗的黑色调;三色灰度都为255时,是最亮的白色调。

在电脑中,RGB的所谓“多少”就是指亮度,并使用整数来表示。通常情况下,RGB各有256级亮度,用数字表示为从0、1、2...直到255。注意虽然数字最高是255,但0也是数值之一,因此共256级。

图1.1 RGB

2.HSV

HSV是一种比较直观的颜色模型,所以在许多图像编辑工具中应用比较广泛,这个模型中颜色的参数分别是:色调(H, Hue),饱和度(S,Saturation),明度(V, Value)。

色调H

用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;

饱和度S

饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。

明度V

明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。

图2.1 HSV

2.1应用openCV中HSV取值范围说明

我们需要注意的在不同应用场景中,HSV取值范围是不尽相同的。

1.PS软件时,H取值范围是0-360,S取值范围是(0%-100%),V取值范围是(0%-100%)。

2.利用openCV中cvSplit函数的在选择图像IPL_DEPTH_32F类型时,H取值范围是0-360,S取值范围是0-1(0%-100%),V取值范围是0-1(0%-100%)。

3.利用openCV中cvSplit函数的在选择图像IPL_DEPTH_8UC类型时,H取值范围是0-180,S取值范围是0-255,V取值范围是0-255。

3.RGB转HSV

3.1公式

3.2代码

测试样例1
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"  /*--------------copyright-hanshanbuleng--------------------*/
// 将色调H的取值范围转换到0~180之间
int main()
{  float H,S,V,H1,S1,V1;IplImage *src = cvLoadImage("F:\\vs2010program\\RGB_HSV\\study_test\\2.jpg", 1);  IplImage *hsv_img = cvCreateImage(cvGetSize(src), 8 , 3);  IplImage *h_img = cvCreateImage(cvGetSize(src), 8, 1);  IplImage *s_img = cvCreateImage(cvGetSize(src), 8, 1);  IplImage *v_img = cvCreateImage(cvGetSize(src), 8, 1);  cvCvtColor(src, hsv_img, CV_BGR2HSV);  cvSplit(hsv_img, h_img, s_img, v_img, NULL);  for(int y = 0; y < hsv_img->height; y++){  for(int x = 0; x < hsv_img->width; x++)  {  H1 = cvGetReal2D(h_img, y, x);S1 = cvGetReal2D(s_img, y, x);V1 = cvGetReal2D(v_img, y, x);//地址法H = (uchar)h_img->imageData[y*h_img->widthStep + x*h_img->nChannels];  S = (uchar)s_img->imageData[y*s_img->widthStep + x*s_img->nChannels];V = (uchar)v_img->imageData[y*v_img->widthStep + x*v_img->nChannels];printf("H:%f  S:%f  V:%f \n",H,S,V);}  }  cvNamedWindow("hsv_img", 0);                   //HSV图cvShowImage("hsv_img", hsv_img); cvNamedWindow("h_img", 0);                     //H通道cvShowImage("h_img", h_img);  cvNamedWindow("s_img", 0);                     //S通道cvShowImage("s_img", s_img);              cvNamedWindow("v_img", 0);                     //V通道cvShowImage("v_img", v_img);  cvWaitKey(0);  cvReleaseImage(&hsv_img);  cvReleaseImage(&h_img);cvReleaseImage(&s_img);cvReleaseImage(&v_img);cvDestroyWindow("hsv_img"); cvDestroyWindow("h_img");cvDestroyWindow("s_img");cvDestroyWindow("v_img");return 0;
}
测试样例2
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"  /*---------------copyright-hanshanbuleng-------------问题描述:
用cvShowImage显示32bits float(IPL_DEPTH_32F)型单通道灰度图像时就出了问题,
图像只有黑白两种颜色,没有灰色的,出现了严重失真,这就是没有正确显示;
问题原因:
如果图像是32位float型,cvShowImage会把像素值乘以255然后再与[0,255]的colormap结合起来显示图像,
也就是说,原来32位folat型图像中值为0的像素被显示成黑色,值大于或等于1的像素被显示成白色。---------------------------------------------------*/
//此时H的范围只能在0~360之间
int main()
{  float H,S,V,H1,S1,V1;IplImage *src = cvLoadImage("F:\\vs2010program\\RGB_HSV\\study_test\\2.jpg", 1);   IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);  cvConvertScale(src, hsv_img, 1.0, 0.0);IplImage *hsv_img1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  IplImage *h_img1 = cvCreateImage(cvGetSize(src), 8, 1);  IplImage *s_img1 = cvCreateImage(cvGetSize(src), 8, 1);  IplImage *v_img1 = cvCreateImage(cvGetSize(src), 8, 1);   cvCvtColor(hsv_img, hsv_img1, CV_BGR2HSV);  cvSplit(hsv_img1, h_img, s_img, v_img, NULL);  for(int y = 0; y < hsv_img->height; y++){  for(int x = 0; x < hsv_img->width; x++)  {  H1 = cvGetReal2D(h_img, y, x);   //0-360  S1 = cvGetReal2D(s_img, y, x);   //0-1V1 = cvGetReal2D(v_img, y, x);   //0-255地址法  还是有问题  待研究//H = (double)h_img->imageData[y*h_img->widthStep + x*h_img->nChannels];  //S = s_img->imageData[y*s_img->widthStep + x*s_img->nChannels];//V = v_img->imageData[y*v_img->widthStep + x*v_img->nChannels];printf("H:%f  S:%f  V:%f \n",H1,S1,V1);}  }  cvCvtScale(v_img,h_img1,255.0/360.0);cvNamedWindow("hsv_img");                   //HSV图cvShowImage("hsv_img", hsv_img); cvNamedWindow("h_img");                     //H通道    0-360 显示不正常cvShowImage("h_img", h_img);  cvNamedWindow("s_img");                     //S通道    0-1 cvShowImage("s_img", s_img);              cvNamedWindow("h_img1");                    //V通道   0-255cvShowImage("h_img1", h_img1);  cvNamedWindow("v_img");               cvShowImage("v_img", v_img);  cvWaitKey(0);  cvReleaseImage(&hsv_img);  cvReleaseImage(&h_img);cvReleaseImage(&s_img);cvReleaseImage(&v_img);cvDestroyWindow("hsv_img"); cvDestroyWindow("h_img");cvDestroyWindow("s_img");cvDestroyWindow("v_img");return 0;
}  
测试样例3
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"  /*--------------copyright-hanshanbuleng--------------------*/
//此时H,S,V的范围均在0~255之间
int main()
{  float H,S,V,H1,S1,V1;IplImage *src = cvLoadImage("F:\\vs2010program\\RGB_HSV\\study_test\\2.jpg", 1);  IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);  cvConvertScale(src, hsv_img, 1.0, 0.0); IplImage *hsv_img1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  IplImage *h = cvCreateImage(cvGetSize(src), 8, 1);  IplImage *s = cvCreateImage(cvGetSize(src), 8, 1);  IplImage *v = cvCreateImage(cvGetSize(src), 8, 1);  cvCvtColor(hsv_img, hsv_img1, CV_BGR2HSV);  cvSplit(hsv_img1, h_img, s_img, v_img, NULL);  //转换表示范围cvConvertScale(h_img, h, (1.0/360)*255, 0.0); cvConvertScale(s_img, s, 255.0, 0.0);  cvConvertScale(v_img, v, 1.0, 0.0);for(int y = 0; y < hsv_img->height; y++){  for(int x = 0; x < hsv_img->width; x++)  {  //转换后的h_img,s_img,v_img 取值查看/*----------------------------------*///转换后的h,s,v 取值查看
//          H1 = cvGetReal2D(h_img, y, x);
//          S1 = cvGetReal2D(s_img, y, x);
//          V1 = cvGetReal2D(v_img, y, x);
//
//          //地址法 对比
//          H = (double)h_img->imageData[y*h_img->widthStep + x*h_img->nChannels];
//          S = (double)s_img->imageData[y*s_img->widthStep + x*s_img->nChannels];
//          V = v_img->imageData[y*v_img->widthStep + x*v_img->nChannels];/*----------------------------------*///转换后的h,s,v 取值查看/*----------------------------------*/H1 = cvGetReal2D(h, y, x);S1 = cvGetReal2D(s, y, x);V1 = cvGetReal2D(v, y, x);//地址法 对比H = (uchar)h->imageData[y*h->widthStep + x*h->nChannels];  S = (uchar)s->imageData[y*s->widthStep + x*s->nChannels];V = (uchar)v->imageData[y*s->widthStep + x*s->nChannels];/*----------------------------------*/printf("H:%f  S:%f  V:%f \n",H,S,V);}  }  cvNamedWindow("hsv_img", 0);                   //HSV图cvShowImage("hsv_img", hsv_img); cvNamedWindow("h_img", 0);                     //H通道cvShowImage("h_img", h_img);  cvNamedWindow("s_img", 0);                     //S通道cvShowImage("s_img", s_img);              cvNamedWindow("v_img", 0);                     //V通道cvShowImage("v_img", v_img);  cvWaitKey(0);  cvReleaseImage(&hsv_img);  cvReleaseImage(&h_img);cvReleaseImage(&s_img);cvReleaseImage(&v_img);cvDestroyWindow("hsv_img"); cvDestroyWindow("h_img");cvDestroyWindow("s_img");cvDestroyWindow("v_img");return 0;
}  
 

4.引申—本实例使用opencv函数简介

函数介绍百度一下就可以,在此我只是简单说明一下

cvLoadImage() //加载图片

cvCreateImage()//创建图片大小

cvCvtColor()  //空间转换

cvSplit()     //分离不同通道

cvCvtScale()  //调整比例

cvNamedWindow()//创建图像显示窗口

cvReleaseImage()//释放创建的图片

cvWaitKey()    //等待

cvDestroyWindow()//销毁窗口


5.参考链接

https://blog.csdn.net/yangdashi888/article/details/53782481

https://blog.csdn.net/zhupananhui/article/details/21157541

https://baike.baidu.com/item/HSV/547122

 

从 RGB 到 HSV 的转换详细介绍相关推荐

  1. SPDIF 色差输出 视频输出 S-Video YUV YCbCr YPbPr RGB VGA WXGA 分别的详细介绍 视频方式接口简介

    SPDIF 色差输出 视频输出 S-Video YUV YCbCr YPbPr RGB VGA WXGA 分别的详细介绍 视频方式接口简介 2008年04月05日 星期六 00:27 SPDIF 数字 ...

  2. FPGA实现RGB转HSV的转换

    FPGA实现RGB转HSV的转换 欢迎添加QQ:2639406604一起交流 1 RGB色彩空间 在图像处理中,最常见的就是RGB色彩模型.在RGB模型中,每种颜色出现在红.绿.蓝的原色光谱分量中.该 ...

  3. 由RGB到HSV的转换详解

    由RGB到HSV的转换详解 1RGB色彩空间 在图像处理中,最常见的就是RGB色彩模型.在RGB模型中,每种颜色出现在红.绿.蓝的原色光谱分量中.该模型基于笛卡尔坐标系.如图1所示,RGB原色值位于3 ...

  4. RGB到HSV色彩空间转换表

    RGB到HSV色彩空间转换表

  5. STC32G12K128-Beta WS2812控制 RGB与HSV互相转换

    ws2812控制代码 void WS2812_bit(bit data_bit) {if(data_bit){LED=1;_nop_();_nop_();_nop_();_nop_();_nop_() ...

  6. Opencv的RGB到HSV颜色空间转换

    从 RGB 到 HSL 或 HSV 的转换 设 (r, g, b) 分别是一个颜色的红.绿和蓝坐标,它们的值是在 0 到 1 之间的实数.设 max 等价于 r, g 和 b 中的最大者.设 min ...

  7. RGB 和 HSV 互相转换算法

    一.简介 RGB 是我们接触最多的颜色空间,分别为红色(R),绿色(G)和蓝色(B).HSV 是用色调H,饱和度S,明亮度V来描述颜色的变化,H取值范围为0°-360°,从红色开始按逆时针方向计算,红 ...

  8. RGB与HSV颜色空间转换

    RGB转化到HSV的算法: max=max(R,G,B): min=min(R,G,B): V=max(R,G,B): S=(max-min)/max: HSV颜色空间模型(圆锥模型) [2] if  ...

  9. Python进制转换详细介绍

    Python为我们提供了强大的内置函数和格式化数字的方法去实现进制转换的功能,下面一一介绍. 先将所有的函数罗列出来,如下: ↓ 2进制 8进制 10进制 16进制 2进制 - bin(int(n,8 ...

最新文章

  1. 转:场景管理--BSP
  2. Simulink仿真 第四节 总线及示波器模块
  3. Java设计模式GOF之6大设计原则
  4. hdu 5340(manacher+枚举)
  5. json对象和json字符串之间的转化
  6. 一套代码编译出ios和android,Hippy: Hippy 是一个新生的跨端开发框架,目标是使开发者可以只写一套代码就直接运行于三个平台(iOS、Android 和 Web)...
  7. Java图片处理(二)图片加水印
  8. QPW 邀请日志表(tf_invite_log)
  9. Channel使用技巧
  10. 阿里日马云开启直播首秀,谈年轻人压力大:一句话给“骂”醒了!
  11. Nginx gzip参数详解及常见问题(已解决)
  12. 程序员,30岁前最好都找大厂,好好做技术
  13. 一些机器学习(Machine Learning)的网站总结
  14. [Java] - 项目中的防止同用户异地登录问题
  15. Android控件组合应用四
  16. python多线程网易云歌单
  17. 5000字干货 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结
  18. 努比亚z11mini 使用 移动物联卡
  19. 脚注交叉引用序号不一样_不为人知的Word交叉引用设置
  20. redis 安装

热门文章

  1. [python]的functools.partial(偏函数)
  2. 【初级程序员】的十点提升建议,以及10个【程序员】的好习惯,让你“秃”然变强
  3. python-名字按拼音排序-(用pypinyin)
  4. SqlSugar.SqlSugarException: English Message : Connection open error . 给定关键字不在字典中
  5. 达梦数据库修改字段(列)(基表修改语句)
  6. 关于自己搭建的邮件被微软反垃圾邮件标记为垃圾邮件
  7. BOOST升压电路参数计算
  8. idea鼠标放大字体设置
  9. DB、DBMS、SQL分别是什么,有什么关系?
  10. 信息传播( information diffusion )