車輛顏色識別 opencv

車輛顏色識別基本原理:

1、將圖像格式轉爲HSV

2、統計HSV各個通道的分佈情況

3、將分佈於顏色區間對應起來,統計各個顏色的數量

4、顏色數量最多的爲車輛顏色

 

一般對顏色空間的圖像進行有效處理都是在HSV空間進行的,然後對於基本色中對應的HSV分量需要給定一個嚴格的範圍,下面是通過實驗計算的模糊範圍

H:  0 — 180

S:  0 — 255

V:  0 — 255

車輛顏色識別數據集

具體實現:

/* 輸入(cv::Mat): 車輛顏色圖片;
   輸出(std::string): 車輛名*/
std::string recognizeVehicleColor1(const cv::Mat& img)
{
	cv::Size imgSize = img.size();
	cv::Mat preImg = img(cv::Rect(imgSize.width*0.15, imgSize.height*0.15, imgSize.width*(1 - 0.3), imgSize.height*(1 - 0.3)));
	// HSV 三通道操作
	imshow("preImg", preImg);
	cv::waitKey();
	cv::Mat hsvImg;
	cv::cvtColor(preImg, hsvImg, CV_BGR2HSV);
	std::vector<cv::Mat> hsv_planes;
	cv::split(hsvImg, hsv_planes);    // 分離HSV通道
	cv::Mat hMask, sMask, vMask;

	cv::threshold(hsv_planes[1], sMask, 43, 255, cv::THRESH_BINARY);	// 以43爲閾值將S通道進行二值化  43來自 HSV基本顏色分量範圍
	//cv::multiply(sMask, bgrMask / 255, hMask);						// 與背景 Mask 合成爲一個 Mask

	cv::threshold(hsv_planes[2], vMask, 46, 255, cv::THRESH_BINARY);	// 以46爲閾值將V通道進行二值化  46來自 HSV基本顏色分量範圍
	cv::multiply(vMask, sMask / 255, hMask);						// 與背景 Mask 合成爲一個 Mask 用於H通道

	cv::threshold(hsv_planes[1], vMask, 43, 255, cv::THRESH_BINARY_INV);// 以43爲閾值將S通道進行二值化 用於V通道

	// 利用二值圖 Mask 將 HSV 通道中的背景部分設爲 0.
	hsv_planes[1] = hsv_planes[2].clone();
	cv::multiply(hsv_planes[0], hMask / 255, hsv_planes[0]);
	cv::multiply(hsv_planes[2], vMask / 255, hsv_planes[2]);

	// 分別計算三個通道的顏色直方圖
	int histSize = 180;         // 將色調量化到180個級別 對應 H 取值範圍 [0:180]
	float ranges[] = { 0, 180 };
	const float* hRanges = { ranges };
	cv::Mat hsv_hist, sv_hist, v_hist;
	//計算直方圖
	calcHist(&hsv_planes[0], 1, 0, cv::Mat(), hsv_hist, 1, &histSize, &hRanges, true, false);
	histSize = 256;
	ranges[1] = 256;
	const float* Ranges = { ranges };
	calcHist(&hsv_planes[2], 1, 0, cv::Mat(), sv_hist, 1, &histSize, &Ranges, true, false);
	calcHist(&hsv_planes[1], 1, 0, cv::Mat(), v_hist, 1, &histSize, &Ranges, true, false);
	std::map<std::string, float> color;	// 定義顏色映射, 對每個顏色對應的HSV區間內進行統計
	color["red"] = 0;
	color["orange"] = 0;
	color["yellow"] = 0;
	color["green"] = 0;
	color["cyan"] = 0;
	color["blue"] = 0;
	color["violet"] = 0;
	color["black"] = 0;
	color["grey"] = 0;
	color["white"] = 0;
	for (int r = 0; r < hsv_hist.rows; r++) {
		float binVal = hsv_hist.at<float>(r);
		if ((r <= 10 && r > 0) || (r >= 160))  // 紅色區間 H [0,10]
		{
			color["red"] += binVal;
		}
		else if (r >= 11 && r <= 25)  // 橙色區間 H [11,25]
		{
			color["orange"] += binVal;
		}
		else if (r >= 26 && r <= 34)  // 黃色區間 H [26,34]
		{
			color["yellow"] += binVal;
		}
		else if (r >= 35 && r <= 77)  // 綠色區間 H [35,77]
		{
			color["green"] += binVal;
		}
		else if (r >= 78 && r <= 99)  // 青色區間 H [78,99]
		{
			color["cyan"] += binVal;
		}
		else if (r >= 100 && r <= 124)  // 藍色區間 H [100,124]
		{
			color["blue"] += binVal;
		}
		else if (r >= 125 && r <= 159)  // 紫色區間 H [125,155]
		{
			color["violet"] += binVal;
		}
	}
	for (int r = 1; r < sv_hist.rows; r++) {
		float sv_binVal = sv_hist.at<float>(r);
		if (r > 200)
		{
			color["white"] += sv_binVal;	// 白色區間 H [200,255]
		}
	}
	for (int r = 1; r < v_hist.rows; r++) {
		float v_binVal = v_hist.at<float>(r);
		if (r > 0 && r <= 46)
		{
			color["black"] += v_binVal;		// 黑色區間 H [0,40]
		}
	}
	float maxVal = 0;
	std::string result = "";
	std::map<std::string, float> ::const_iterator it = color.begin();  //找出對應顏色區間統計數最多的顏色
	for (it; it != color.end(); it++)
	{
		if (it->second > maxVal)
		{
			maxVal = it->second;
			result = it->first;
		}
	}
	return result;
}
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章