3 OpenCV 车牌识别-2 颜色定位

HSV颜色模型

如果我们想找出一副图像中的蓝色部分,我们需要检查rgb分量中的blue分量就可以了。一般blue分量是0-255的值,即便蓝色分量255了,由于另外两个分量的影响,需要考虑各个分量的配比问题,rgb作为颜色判断很难实现,就有了hsv模型hsv,photoshop中hsb

HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。

在这里插入图片描述

色调H

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

饱和度S

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

亮度V

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

在OpenCV中hsv 数据为8UC则取值分别为 0-180 0-255 0-255 ,即蓝色240对应的应该是120

在这里插入图片描述

1, 预处理
//src目前是BGR颜色空间,转换成HSV

	Mat hsv;
	cvtColor(src, hsv, COLOR_BGR2HSV);
	//imshow("hsv", hsv);

效果
在这里插入图片描述
2找蓝色像素:h(100-124),s(43-255),v(46-255)
遍历
获取通道数

	int channels = hsv.channels();
	int height = hsv.rows;
	//如下图,宽度变成了列数乘以3
	int width = hsv.cols * channels;
	//如果是连续存储,按照1行来处理,如下图,内存地址从0到8为第一行,将下一行看作为一行。
	if (hsv.isContinuous()) {
		width *= height;
		height = 1;
	}

uchar* p;
	for (int i = 0; i < height; i++)
	{
		//取第i行的数据
		p = hsv.ptr<uchar>(i);
		//每次处理channels个数据,这里j步长为channels,每次都取3个。
		for (int j = 0; j < width; j += channels) {
			//获取 h s v 分量
			int h = p[j];
			int s = p[j + 1];
			int v = p[j + 2];
			//h(100-124),s(43-255),v(46-255)
			bool isBlue = false;
			if (h >= 100 && h <= 124 &&
				s >= 43 && s <= 255 &&
				v >= 46 && v <= 255
				) {
				isBlue = true;
			}
			if (isBlue)
			{
				//凸显蓝色(v分量最大255)
				p[j] = 0;//h
				p[j + 1] = 0;//s
				p[j + 2] = 255;//v
			}
			else {
				//变黑(v分量为0)
				p[j] = 0;//h
				p[j + 1] = 0;//s
				p[j + 2] = 0;//v
			}
		}
	}// end for
	//imshow("凸显蓝色", hsv);

在这里插入图片描述
处理完之后如图:
在这里插入图片描述如果是蓝色的车,可能就识别不了了。

	vector<Mat> hsv_split;
	split(hsv, hsv_split);//对图像按通道进行分离 , merge()合并

	//imshow("分离v分量", hsv_split[2]);//v分离

在这里插入图片描述

https://blog.csdn.net/u012819339/article/details/82222008

分离 之后如图:
在这里插入图片描述
分离分量之后,和sobel一样,进行二值化,闭操作,找轮廓。。。

注意:
之前的是蓝色的,还有一种是黄色的。
//蓝色车牌:字符浅背景深,正二值化
//黄色车牌:字符深背景浅,反二值化


	//二值化
	Mat shold;
	//THRESH_OTSU 大律法 自适应阈值
	//THRESH_BINARY 正二值化
	//THRESH_BINARY_INV 反二值化
	//蓝色车牌:字符浅背景深,正二值化
	//黄色车牌:字符深背景浅,反二值化
	threshold(hsv_split[2], shold, 0, 255, THRESH_OTSU + THRESH_BINARY);
	//imshow("color二值化", shold);
	//闭操作
	Mat close;
	Mat element = getStructuringElement(MORPH_RECT, Size(17, 3));
	morphologyEx(shold, close, MORPH_CLOSE, element);
	//imshow("color闭操作", close);

	//找轮廓
	vector<vector<Point>> contours;
	findContours(close, //输入图像
		contours, //输出轮廓
		RETR_EXTERNAL, //外轮廓
		CHAIN_APPROX_NONE	//轮廓上所有像素点
	);
	RotatedRect rotatedRect;
	vector<RotatedRect> vec_color_rects;
	//遍历并判断矩形尺寸
	Mat src_clone = src.clone();
	for each (vector<Point> points in contours)
	{
		rotatedRect = minAreaRect(points);//带角度的矩形
		rectangle(src_clone, rotatedRect.boundingRect(), Scalar(0, 0, 255));
		if (verifySizes(rotatedRect)) {
			vec_color_rects.push_back(rotatedRect);
		}
	}
	for each (RotatedRect rect in vec_color_rects)
	{
		rectangle(src_clone, rect.boundingRect(), Scalar(0, 255, 0));
	}
	//imshow("color找轮廓", src_clone);
	//矩形矫正(角度判断,旋转矩形,调整大小)
	tortuosity(src, vec_color_rects, dst_plates);
	/*for each (Mat m in dst_plates)
	{
		//imshow("color定位候选车牌", m);
		//waitKey();
	}*/



color二值化:
在这里插入图片描述sobel二值化
在这里插入图片描述
sobel闭操作(左)和color闭操作(右边)图对比
在这里插入图片描述显然,color闭操作要好一点。

发布了93 篇原创文章 · 获赞 26 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/sxj159753/article/details/102419030