1. 程式人生 > >HSV取值範圍

HSV取值範圍

這次我主要說說顏色空間,包括三個方面:RGB顏色空間,HSV顏色空間以及顏色空間的轉換

RGB顏色空間介紹:

1:RGB顏色空間簡介

         三基色原理:大多數的顏色可以通過紅、綠、藍<數學中基的概念>三色按照不同的比例合成產生,同樣絕大多數單色光也可以分解成紅綠藍三種色光

         紅綠藍三基色按照不同的比例相加合成混色稱為相加混色。其中一些混色的規律有:

                   紅色+綠色 = 黃色

                   綠色+藍色 = 青色

                   紅色+藍色 = 品紅

                   紅色+綠色+藍色 = 白色

                   紅色+青色 = 白色

                   綠色+品紅 = 白色

                   藍色+黃色 = 白色

下圖為RGB空間:

2:互補光的定義:

         當兩種光按照適當比例混合得到白光時,稱這兩種光為互補光。所以上述的混色規律我們可以得到青色、黃色、品紅分別是紅色、藍色、綠色的補色。

3:亮度的定義:

         單色光的亮度強度各不相同,根據人的感受是:綠光最高,紅光次之,藍光最弱,假設得到的白光的強度為100%。如果用Y表示景物的亮度,則通常有:

                   Y= 0.299R + 0.587G + 0.114B

因為紅﹑綠﹑藍三基色能夠合成自然界所有的色彩,因此在電子裝置和軟體中,經常使用紅綠藍三基色合成五顏六色的影象。用以上的相加混色所表示的顏色模式成為RGB模式

注意:

1:CvLoadImage(“”,0)所得到的影象即為灰度單通道影象,所對應的畫素即為Y;而與split函式得到的單通道影象R,G,B不一樣,但其亮度顯示也是按照下圖的直線來顯示的<即為RGB空間的直線>

2:三通道影象也可能是灰度影象,當三通道值相等時,所對應的三通道影象就是灰度影象<可以通過以下程式畫出來>。即RGB space空間中(0,0,0)和(1,1,1)兩線上所有點就是灰度影象—>三通道圖不一定是彩色的,彩色圖一定是三通道的

3:cvCvtColor(src,dst,CV_GRAY2BGR);  //此時dst三通道的值都相等,都等於src單通道的值,因此結果仍然是灰度影象,這個函式實質不起任何作用。。

4:單通道影象亮度顯示也是通過下圖來顯示的

得到上圖的程式碼為:

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. #include <iostream>
  2. #include "cv.h"
  3. #include "highgui.h"
  4. #include "cxcore.h"
  5. usingnamespace std;  
  6. int main()  
  7. {  
  8.     IplImage *dst = cvCreateImage(cvSize(255, 255), 8, 3);  
  9.     for(int y = dst->height - 1; y >= 0; y--)  
  10.     {  
  11.         cvSet2D(dst, y,  dst->height - y - 1, cvScalar(255-y, 255-y, 255-y));  
  12.     }  
  13.     cvNamedWindow("show");  
  14.     cvShowImage("show", dst);  
  15.     cvWaitKey(0);  
  16.     cvReleaseImage(&dst);  
  17.     cvDestroyWindow("show");  
  18.     return 0;  
  19. }  

HSV顏色空間

H:色調 0°對應紅色, 120°對應綠色, 240°對應藍色---對應不同的顏色取值範圍0~360

S:飽和度  比若說:紅色的純度,越白純度越低,取值範圍0~1

V:亮度  比如你穿了一件紅色衣服在白天亮度較高(0~255之間)傍晚或者黃昏就比較低(0~255之間)即多少的光照上去反射出來被看見,取值範圍0~255,因為其轉換公式是統一的,如下:


注意:其實不同的軟體進行量化的取值範圍是不同的,例如PS軟體裡的h取值為0-360、s取值為0-1、v取值為0-1.

而opencv裡cvSplit使用的影象是32F則其取值是h為0-360、s取值為0-1、v取值為0-255。如果是8UC則取值範圍是h為0-180、s取值為0-255、v取值是0-255.  其中h色調對影象的分辨是很準的。

如圖:


注意: 如果一個顏色的飽和度偏低,會導致色調資訊變得不穩定以及不可靠。這是因為低飽和度的顏色中,紅綠藍三個分量幾乎是相等的。這使得難以確定精確的顏色。

顏色空間的轉換

用到的核心函式有: cvConvertScale, cvSplit, cvMerge, cvCvtColor

需要注意的是:由於載入進來影象是uchar,最多隻能是255,而OpenCV正常程式的結構顯示H色調都會小於等於180<因為程式知道表示不了360,直接全部縮小到180>,而H色調的取值範圍0~360,因此我們需要將影象轉換成float型別,而cvConvertScale 可以實現放大縮小偏移同時可以做型別轉換;之後我們可以將hsv各通道轉換到0~255之間,使用到的函式仍然是cvConvertScale 。最後需要注意的一點是:CvShowImage顯示的影象都會被當做RGB顏色空間的影象來處理.

下面給出這之間範圍變化的程式碼:

1:沒有考慮H(色調)範圍的程式碼,此時H的範圍只能在0~180之間。

程式碼:

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. #include <iostream>
  2. #include "cv.h"
  3. #include "highgui.h"
  4. #include "cxcore.h"
  5. usingnamespace std;  
  6. int main()  
  7. {  
  8.     IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);  
  9.     IplImage *hsv_img = cvCreateImage(cvGetSize(src), 8 , 3);  
  10.     IplImage *h_img = cvCreateImage(cvGetSize(src), 8, 1);  
  11.     IplImage *s_img = cvCreateImage(cvGetSize(src), 8, 1);  
  12.     IplImage *v_img = cvCreateImage(cvGetSize(src), 8, 1);  
  13.     cvCvtColor(src, hsv_img, CV_BGR2HSV);  
  14.     cvSplit(hsv_img, h_img, s_img, v_img, NULL);  
  15.     for(int y = 0; y < hsv_img->height; y++){  
  16.         for(int x = 0; x < hsv_img->width; x++)  
  17.         {  
  18.             cout << cvGetReal2D(h_img, y, x) << " ";  
  19.         }  
  20.         cout << endl;  
  21.     }  
  22.     cvNamedWindow("src", 0);  
  23.     cvShowImage("src", hsv_img);  
  24.     cvWaitKey(0);  
  25.     cvReleaseImage(&src);  
  26.     cvDestroyWindow("src");  
  27.     return 0;  
  28. }  

2:將色調H的取值範圍轉換到0~360之間

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. #include <iostream>
  2. #include "cv.h"
  3. #include "highgui.h"
  4. #include "cxcore.h"
  5. usingnamespace std;  
  6. int main()  
  7. {  
  8.     IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);  
  9.     IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);  
  10.     cvConvertScale(src, src_float, 1.0, 0.0);  
  11.     IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);  
  12.     IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  13.     IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  14.     IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  15. </span>  
  16.     cvCvtColor(src_float, hsv_img, CV_BGR2HSV);  
  17.     cvSplit(hsv_img, h_img, s_img, v_img, NULL);  
  18.     for(int y = 0; y < hsv_img->height; y++){  
  19.         for(int x = 0; x < hsv_img->width; x++)  
  20.         {  
  21.             cout << cvGetReal2D(h_img, y, x) << " ";  
  22.         }  
  23.         cout << endl;  
  24.     }  
  25.     cvNamedWindow("src", 0);  
  26.     cvShowImage("src", hsv_img);  
  27.     cvWaitKey(0);  
  28.     cvReleaseImage(&src);  
  29.     cvDestroyWindow("src");  
  30.     return 0;  
  31. }  

3:將H,S,V的範圍轉化到0~255之間

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. #include <iostream>
  2. #include "cv.h"
  3. #include "highgui.h"
  4. #include "cxcore.h"
  5. usingnamespace std;  
  6. int main()  
  7. {  
  8.     IplImage *src = cvLoadImage("F:\\tongtong.jpg", 1);  
  9.     IplImage *src_float = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F, 3);  
  10.     cvConvertScale(src, src_float, 1.0, 0.0);  
  11.     IplImage *hsv_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F , 3);  
  12.     IplImage *h_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  13.     IplImage *s_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  14.     IplImage *v_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);  
  15.     IplImage *h = cvCreateImage(cvGetSize(src), 8, 1);  
  16.     IplImage *s = cvCreateImage(cvGetSize(src), 8, 1);  
  17.     IplImage *v = cvCreateImage(cvGetSize(src), 8, 1);  
  18.     cvCvtColor(src_float, hsv_img, CV_BGR2HSV);  
  19.     cvSplit(hsv_img, h_img, s_img, v_img, NULL);  
  20.     cvConvertScale(h_img, h, (1.0/360)*255, 0.0);  
  21.     cvConvertScale(s_img, s, 255.0, 0.0);  // 因為S的取值範圍為0~1,因為其是32F,如果是8uc則是0-255
  22.     cvConvertScale(v_img, v, 1.0, 0.0); 
  23.     for(int y = 0; y < hsv_img->height; y++){  
  24.         for(int x = 0; x < hsv_img->width; x++)  
  25.         {  
  26.             if(cvGetReal2D(h, y, x) > 200)cout << cvGetReal2D(h, y, x) << " ";  
  27.         }  
  28.         cout << endl;  
  29.     }  
  30.     cvNamedWindow("src", 0);  
  31.     cvShowImage("src", hsv_img);  
  32.     cvWaitKey(0);  
  33.     cvReleaseImage(&src);  
  34.     cvDestroyWindow("src");  
  35.     return 0;  
  36. }  

相關推薦

HSV範圍

這次我主要說說顏色空間,包括三個方面:RGB顏色空間,HSV顏色空間以及顏色空間的轉換 RGB顏色空間介紹: 1:RGB顏色空間簡介          三基色原理:大多數的顏色可以通過紅、綠、藍<數學中基的概念>三色按照不同的比例合成產生,同樣絕大多

java中為什麽byte的範圍是-128到+127

進制數 符號位 為什麽 絕對值 www .html tar 同學 自己 概念:java中用補碼表示二進制數,補碼的最高位是符號位,最高位為“0”表示正數,最高位為“1”表示負數。正數補碼為其本身;負數補碼為其絕對值各位取反加1

CDM中遍歷域及其約束條件、範圍、引用它的項目

最大值 next folder values active valid cit proc not Option ExplicitValidationMode = TrueInteractiveMode = im_BatchDim mdl ‘當前mod

JAVA基本類型大小與範圍?

false 特殊 數據類型 字節 true ima 指令 它的 ges 布爾類型boolean比較特殊,盡管Java虛擬機定義了boolean類型,但虛擬機對boolean類型的支持是有限的,沒有為boolean值單獨設計JVM指令。操作布爾值的表達式在編譯之後,它使用的

int、long、long long範圍

family lin line ng- sig color long long tom p s unsigned int 0~4294967295 int -2147483648~2147483647 unsigned long 0~4294967295

Java byte 類型的範圍是-128~127

com 基本數據類型 single static 數據 數據類型 blank tle -128 為什麽Java byte 類型的取值範圍是-128~127 : http://blog.163.com/[email protected]/blog/static/47

獲取mips32機器的各數據類型的範圍

2個 ffffff 使用 數據類型 無符號 取值 oid 數據 格式化 一.背景: 使用的mips 32bit機器,32bit的vxworks操作系統(各機器帶來的範圍都不一樣,與操作系統也有關聯) 二.驗證類型的範圍: 2.1 unsigned long: void ma

Java數據類型及對應範圍

小數 日常 java 方法 而且 div 滿足 archive 大寫 Java數據類型及對應取值範圍 在Java中,數據類型分為兩大種:基本數據類型(值類型)和包裝類型(引用數據類型)。基本數據類型不是對象,不能調用toString()、hashCode()、getCl

mysql五種日期類型的範圍

值範圍 字節 etime ear 取值 日期類型 times time sql YEAR ,字節數為1,取值範圍為“1901——2155”DATE,字節數為4,取值範圍為“1000-01-01——9999-12-31”TIME,字節數為3,取值範圍為“-838:59:59—

C#中float的範圍和精度分析

windows系統 weight 3.5 ans adding 發生 mage 深入 wid 本文實例分析了C#中float的取值範圍和精度。分享給大家供大家參考。具體分析如下: float類型的表現形式: 默認情況下,賦值運算符右側的實數被視為 double。 因此

【原始碼追蹤】SparkStreaming 中用 Direct 方式每次從 Kafka 拉多少條資料(offset範圍

我們知道 SparkStreaming 用 Direct 的方式拉取 Kafka 資料時,是根據 kafka 中的 fromOffsets 和 untilOffsets 來進行獲取資料的,而 fromOffsets 一般都是需要我們自己管理的,而每批次的 untilOffsets 是由

SQL 用於各種資料庫的資料型別(轉載) sqlserver 資料型別 範圍 長度

SQL 用於各種資料庫的資料型別 來源 http://www.runoob.com/sql/sql-datatypes.html    面向資料庫程式設計中,資料型別的取值範圍、長度,可能是需要經常檢視的資料。 Microsoft Access、MySQL 和 SQL S

c語言long和long long的範圍

溢位和取值範圍 C語言的整型溢位問題 整數溢位 int、long int 、long long int 佔用位元組 《C和指標》中寫過:long與int:標準只規定long不小於int的長度,int不小於short的長度。 double與int型別的儲存機制不同

C基本資料型別的範圍

int: -2147483648~+2147483647 無符號整型unsigned[int] :0~4294967295。 短整型 short [int]:-32768~32767。 無符號短整型unsigned short[int]:0~65535。 長整型 Long int: -214

leetcode7_C++整數反轉 int、long、long long範圍

小弟不才,有錯誤請指出,謝謝。   給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。   示例 1:   輸入: 123 輸出: 321    示例 2:   輸入: -123 輸

【原創】給定隨機數的範圍(最小、最大),且要求多次取得的隨機數最後的結果有一個固定的平均值

給定隨機數的取值範圍(最小值、最大值),且要求多次取得的隨機數最後的結果有一個固定的平均值。 演算法如下: /****** * author ztg 281099678 2018-12-06 * @param $min float 範圍最小值 * @param $max

mysql的資料型別int、bigint、smallint 和 tinyint範圍

目錄 int 註釋 使用整數資料的精確數字資料型別。 bigint         從 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型資料(所有數字)。儲存大

C語言的整型溢位問題 int、long、long long範圍 最大最小

《C和指標》中寫過:long與int:標準只規定long不小於int的長度,int不小於short的長度。 double與int型別的儲存機制不同,long int的8個位元組全部都是資料位,而double是以尾數,底數,指數的形式表示的,類似科學計數法,因此double比i

常用整型變數的最大範圍

#include<iostream> #include<math.h> #include<limits.h> using namespace std; int main() { // 2^16 = 32768 : unsigned sh

談談gnuplot(五):座標範圍及刻度

http://qbk378.lofter.com/post/b28f6_14f062 我們從上一講結束時的影象開始: gnuplot> set samples 500 gnuplot> set xlabel "X" gnuplot> set ylabel "Y" gnupl