如果要进行颜色检测,HSV颜色空间是当前最常用的。
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。
RGB和CMY颜色模型都是面向硬件的,而HSV(Hue Saturation Value)颜色模型是面向用户的。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。
OpenCV中HSV各个分量的取值范围
色调 H : 0 ~ 180
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°, 蓝色为240°。它们的补色是:黄色为60°,青色为180°, 品红为300°;
饱和度 S :0 ~ 255
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
亮度 V : 0 ~ 255
亮度表示颜色明亮的程度,对于光源色,亮度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
若要识别某种颜色,HSV的3个分量的范围得自己调了,官方的颜色区域不是特别靠谱。
一点经验:亮度V 几乎对颜色的识别没有影响,亮度与颜色大概关系不大,只与环境中的光照有关,为了算法的适应性更强,可以把亮度V的范围调成0~255。
对颜色识别影响最大的是色调,这个得仔细调,当然,为了适应性强,范围最好调宽点。
转换成HSV颜色空间后,居然有种印象派画作的感觉了
以下的程序,能将一幅图像中的 红色、蓝色、黄色找出来:
int main()
{
Mat srcImg = imread("3.jpg");
Mat hsvImg;
//将RGB颜色空间转换为HSV颜色空间
cvtColor(srcImg, hsvImg, COLOR_BGR2HSV); //CV_BGR2YCrCb
imshow("hsv", hsvImg);
int minH = 0; //26
int maxH = 0; //34
int minS = 0; //
int maxS = 0;
int minV = 0; //200
int maxV = 0;
Mat yellowImg, blueImg, redImg;
for (int i = 0; i < 3; i++)
{
switch (i)
{
case 0: //黄色
minH = 16; //26
maxH = 35; //34
minS = 160; //
maxS = 255;
minV = 50; //200
maxV = 255;
// inRange(原图像, 最小值的范围, 最大值的范围, 输出图像); //输出图像是黑白二值图像,其中 最小值<=像素点<=最大值 的像素点是白色
inRange(hsvImg, Scalar(minH, minS, minV), Scalar(maxH, maxS, maxV), yellowImg); //Threshold the image
break;
case 1: //蓝色
minH = 70; //26
maxH = 120; //34
minS = 150; //
maxS = 255;
minV = 50; //200
maxV = 255;
inRange(hsvImg, Scalar(minH, minS, minV), Scalar(maxH, maxS, maxV), blueImg); //Threshold the image
break;
case 2: //红色
minH = 0; //26
maxH = 15; //34
minS = 160; //
maxS = 255;
minV = 50; //200
maxV = 255;
inRange(hsvImg, Scalar(minH, minS, minV), Scalar(maxH, maxS, maxV), redImg);
break;
default:
cout << "颜色标志输入错误" << endl;
}
}
Mat resultImg;
Mat yeBluImg;
//bitwise_or(a, b, ab);
//图像或 ,ab = a||b
bitwise_or(yellowImg, blueImg, yeBluImg); //图像或
bitwise_or(yeBluImg, redImg, resultImg); //图像或
imshow("result", resultImg);
//开操作 (去除一些噪点) 如果二值化后图片干扰部分依然很多,增大下面的size
Mat eleOpen = getStructuringElement(MORPH_RECT, Size(6, 6));
morphologyEx(resultImg, resultImg, MORPH_OPEN, eleOpen);
imshow("open", resultImg);
waitKey(0);
return 0;
}
Mat resultImg;
Mat yeBluImg;
//bitwise_or(a, b, ab);
//图像或 ,ab = a||b
bitwise_or(yellowImg, blueImg, yeBluImg); //图像或
bitwise_or(yeBluImg, redImg, resultImg); //图像或
imshow("result", resultImg);
//开操作 (去除一些噪点) 如果二值化后图片干扰部分依然很多,增大下面的size
Mat eleOpen = getStructuringElement(MORPH_RECT, Size(6, 6));
morphologyEx(resultImg, resultImg, MORPH_OPEN, eleOpen);
imshow("open", resultImg);
waitKey(0);
return 0;
}