一、不同的彩色空间

BGR颜色空间:

    先说一下BGR颜色空间,bgr三原色,人眼中有四种感光细胞,分别是三种红、绿、蓝锥形的刚光细胞,以及感知黑白的杆状细胞,模型如下:

opencv 读取调色板 png opencv色块_计算机视觉

HSV(Hue Saturation、 Value ):

分别代表的是色调、饱和度、亮度。HSV是一种类似于BGR的颜色空间,H:表示的是颜色的类型,S:表示的是从不饱和到饱和,V:表示的是亮度。模型如下:

opencv 读取调色板 png opencv色块_计算机视觉_02

opencv 读取调色板 png opencv色块_opencv_03

 那为啥还要有一个HSV模型?假如说我想提取红色,但是你用BGR颜色模型的提取可以有几百万中可能都是红的的,所以这个BGR模型是有缺陷的,因此提出了HSV模型。下图是从文库中找到的不同颜色的阈值范围:

opencv 读取调色板 png opencv色块_图像处理_04

H(色度)=[0,360],0==red, 120==green,  240==blue

opencv 读取调色板 png opencv色块_opencv_05

 S(饱和度) 色饱和度参数是色环上的从圆点到彩色点的半径

V(亮度) 从0%-100%

opencv 读取调色板 png opencv色块_opencv_06

HSI颜色模型

我们再说一下除了HSV模型,还有一个HSI模型,两者类似,不同在于:I代表亮度,V代表明度。

亮度和明度的区别是:

一种纯色的明度等于白色的明度,而纯色的亮度等于中度灰的亮度。换句话说就是明度是相对于100%而言的,而亮度是相对于50%而言的,模型如下:

opencv 读取调色板 png opencv色块_opencv_07

 二、彩色分割

由于HSV空间中只有一个通道是颜色通道,所以我们一般使用HSV空间来彩色分割。因此我们现需要将一个图像从BGR颜色空间转换到HSV颜色空间,cvCvtColor算子,然后在利用inRange根据HSV设置的范围检测目标。

从RGB到HSL或HSV的转换

设 (rgb)分别是一个颜色的红、绿和蓝坐标,它们的值是在0到1之间的实数。设max等价于rgb中的最大者。设min等于这些值中的最小者。要找到在HSL空间中的 (hsl)值,这里的h ∈ [0, 360)是角度的色相角,而sl ∈ [0,1]是饱和度和亮度,计算为

opencv 读取调色板 png opencv色块_图像处理_08

h的值通常规范化到位于0到360°之间。而h = 0用于max = min的(定义为灰色)时候而不是留下h未定义。

HSL和HSV有同样的色相定义,但是其他分量不同。HSV颜色的sv的值定义如下:

opencv 读取调色板 png opencv色块_算法_09

void inRange(
InputArray src, //输入要处理的图像,可以为单通道或多通道
InputArray lowerb,// 包含下边界的数组或标量(HSV的最小值)
InputArray upperb,//包含上边界数组或标量(HSV的最大值)
 OutputArray dst);//输出图像,与输入图像src 尺寸相同且为CV_8U 类型

opencv 读取调色板 png opencv色块_opencv 读取调色板 png_10

opencv 读取调色板 png opencv色块_计算机视觉_11

 

opencv 读取调色板 png opencv色块_opencv_12

#if  1 // 图像分割  --彩色分割
Mat  img;  //输入图像:
Mat bgr;// 灰度值归一化
Mat hsv;//hsv 图像


// 色相
int hmin = 0;
int hmin_max = 360;
int hmax = 180;
int hmax_max = 180;


//色饱和度

int  smin = 0;
int  smin_max = 255;
int  smax = 255;
int  smax_max = 255;

// 亮度
int vmin = 106;
int vmin_max = 255;
int vmax = 255;
int vmax_max = 255;


string  windowname = "src";
string dstname = "dst";
Mat  dst;

void callback_hsv(int, void*);

int main() {
	img = imread("C:\\Users\\19473\\Desktop\\opencv_images\\528.jpg");
	if (!img.data)
	{
		printf("could not  load  image....\n");
	}
	imshow(windowname,img);
	 bgr = img.clone();
	 namedWindow(dstname, CV_WINDOW_AUTOSIZE);
	// 将bgr 颜色空间转换为HSV
	 cvtColor(bgr,hsv,CV_BGR2HSV);

	 createTrackbar("hmin:", dstname,&hmin, hmin_max, callback_hsv);
	 createTrackbar("hmax:", dstname, &hmax, hmax_max, callback_hsv);

	 createTrackbar("smin:", dstname, &smin, smin_max, callback_hsv);
	 createTrackbar("smax:", dstname, &smax, smax_max, callback_hsv);


	 createTrackbar("vmin:", dstname, &vmin, vmin_max, callback_hsv);
	 createTrackbar("vmax:", dstname, &vmax, vmax_max, callback_hsv);

	 callback_hsv(0,0);
	waitKey(0);
	return 0;
}


void callback_hsv(int, void*) {
	dst = Mat::zeros(img.size(), img.type());
	Mat  mask;//掩码
	inRange(hsv, Scalar(hmin, smin, vmin), Scalar(hmin_max, smin_max, vmin_max), mask);  //掩码得到原图的转换
	for (int r = 0; r < bgr.rows; r++)
	{
		for (int c = 0; c < bgr.cols; c++)
		{
			if (mask.at<uchar>(r, c) == 255)
			{
				dst.at<Vec3b>(r, c) = bgr.at<Vec3b>(r, c);
			}
		}
	}
	imshow(dstname, dst);
}
#endif