车辆颜色识别 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;
}
 

 

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