1. 程式人生 > >基於Opencv的顏色識別

基於Opencv的顏色識別

彩色模型  

   數字影象處理中常用的採用模型是RGB(紅,綠,藍)模型和HSV(色調,飽和度,亮度),RGB廣泛應用於彩色監視器和彩色視訊攝像機,我們平時的圖片一般都是RGB模型。而HSV模型更符合人描述和解釋顏色的方式,HSV的彩色描述對人來說是自然且非常直觀的。

HSV模型

HSV模型中顏色的引數分別是:色調(H:hue),飽和度(S:saturation),亮度(V:value)。由A. R. Smith在1978年建立的一種顏色空間, 也稱六角錐體模型(Hexcone Model)。

(1)色調(H:hue):用角度度量,取值範圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍色為240°。它們的補色是:黃色為60°,青色為180°,品紅為300°;

(2)飽和度(S:saturation):取值範圍為0.0~1.0,值越大,顏色越飽和。

(3)亮度(V:value):取值範圍為0(黑色)~255(白色)

RGB轉成HSV

設 (r, g, b) 分別是一個顏色的紅、綠和藍座標,它們的值是在 0 到 1 之間的實數。設 max 等價於 r, g 和 b 中的最大者。設 min 等於這些值中的最小者。要找到在 HSV 空間中的 (h, s, v) 值,這裡的 h ∈ [0, 360)是角度的色相角,而 s, v ∈ [0,1] 是飽和度和亮度,方法如下:

  • max=max(R,G,B)

  • min=min(R,G,B)

  • if R = max, H = (G-B)/(max-min)

  • if G = max, H = 2 + (B-R)/(max-min)

  • if B = max, H = 4 + (R-G)/(max-min) 

  • H = H * 60

  • if H < 0, H = H + 360

  • V=max(R,G,B)
  • S=(max-min)/max

    OpenCV下有個函式可以直接將RGB模型轉換為HSV模型,OpenCV中H∈ [0, 180), S ∈ [0, 255], V ∈ [0, 255]。我們知道H分量基本能表示一個物體的顏色,但是S和V的取值也要在一定範圍內,因為S代表的是H所表示的那個顏色和白色的混合程度,也就說S越小,顏色越發白,也就是越淺;V代表的是H所表示的那個顏色和黑色的混合程度,也就說V越小,顏色越發黑。經過實驗,識別藍色的取值是 H在100到140,S和V都在90到255之間。一些基本的顏色H的取值可以如下設定:

Orange 0-22,Yellow 22- 38,Green 38-75,Blue 75-130,Violet 130-160,Red 160-179

具體實現

(1) 讀取一張圖片

    cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV);

(2)將彩色影象均衡化 

    split(imgHSV, hsvSplit);

    equalizeHist(hsvSplit[2],hsvSplit[2]);

    merge(hsvSplit,imgHSV);

(3)檢測顏色

    inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded);

   (4)進行開操作和閉操作,去除噪聲的影響。

    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));

    morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);

    morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);

#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>

using namespace cv;
using namespace std;

//入口主函式
int main(int argc, char** argv)
{
	//開啟攝像頭,從攝像頭獲取影象
	VideoCapture cap(0);
	if (!cap.isOpened())
	{
		cout << "Cannot open the web cam"<<endl;
		return -1;
	}
	//建立視窗
	namedWindow("Control",CV_WINDOW_AUTOSIZE);
	
	int iLowH = 100;
	int iHighH = 140;

	int iLowS = 90;
	int iHighS = 255;

	int iLowV = 90;
	int iHighV = 255;
	//建立進度條
	cvCreateTrackbar("LowH","Control",&iLowH,179);
	cvCreateTrackbar("HighH", "Control", &iHighH,179);

	cvCreateTrackbar("LowS", "Control", &iLowS,255);
	cvCreateTrackbar("Highs", "Control", &iHighS,255);

	cvCreateTrackbar("LowV", "Control", &iLowV,255);
	cvCreateTrackbar("HighV", "Control", &iHighV,255);
	//while迴圈載入圖片
	while (true)
	{
		Mat imgOriginal;
		bool bSuccess = cap.read(imgOriginal);
        
		if (!bSuccess)
		{
			cout << "Cannot read a frame from video stream" << endl;
				break;
		}
		//
		Mat imgHSV;
		vector<Mat> hsvSplit;
		cvtColor(imgOriginal,imgHSV,COLOR_BGR2HSV);

		//轉化成直方圖均衡化
		split(imgHSV,hsvSplit);
		equalizeHist(hsvSplit[2],hsvSplit[2]);
		merge(hsvSplit,imgHSV);
		Mat imgThresholded;
		//確定顏色顯示的範圍
		inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS,iHighV),imgThresholded);
		//去除噪點
		Mat element = getStructuringElement(MORPH_RECT,Size(5,5));
		morphologyEx(imgThresholded,imgThresholded,MORPH_OPEN,element);
	    //連線連通域
		morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);
		imshow("Thresholded Image",imgThresholded);
		imshow("Original",imgOriginal);
		//等待時間
		char Key = (char)waitKey(300);
		if (Key==27)
		{
			break;
		}
	}
	return 0;
}