目录

  • 1 HSV颜色空间
  • 2 关于Matlab的hsv实现
  • 3 关于OpenCV的hsv实现

1 HSV颜色空间

  1. 常见的颜色空间是RGB、HSV等,大部分图像都是RGB图像形式存在。但是在不同软件下RGB的读入内存的顺序不一样,比如, OpenCV中是以BGR的顺序排列,Qt和MATLAB是以RGB的顺序排列,不过都提供相关顺序转换函数,不用太担心。
  2. HSV颜色空间更加适合颜色的判断,比如想要找到蓝色车牌、黄色车牌等,这时候HSV比RGB更容易处理。
  3. HSV的第一个通道是H(Hue-色调),负责颜色;第二个通道是S(Saturation-饱和度),负责光的纯度,饱和度高,颜色则深而艳,比如S=0,就是灰度图片了;第二个通道是V(Value-亮度),负责亮度,比如V=0,就是黑色图片了,这三个值取值范围在不同工具会不同,但是标准的HSV的取值范围是一样的,只是转换了取值范围以适应自己的工具箱。下面我们会看到这个现象。
  4. 各种颜色空间本质对同一个事物的不同描述而已。
  5. 本次重点是OpenCV中怎么使用,MATLAB只是引子

2 关于Matlab的hsv实现

我参考了一篇文章,还很好,链接
下面就简单的看看选取蓝色的方法。
首先,最重要的是H与颜色的对应值,MATLAB的H通道是0-1,其具体对应图如下图所示。

opencvdrawContours颜色设置透明度_OpenCV


在这里,我选取了蓝色,根据上图选择了0.55-0.7的范围,实际中你可以微调下阈值,以便更好适应。

close all;clear all;clc;
I = imread('78.bmp');%读入图片
figure,imshow(I);
I_h = rgb2hsv(I);%RGB转hsv
figure,imshow(I_h);
[height, width, c] = size(I);
for i = 1:height
    for j = 1:width
        h = I_h(i,j,1);
        s = I_h(i,j,2);
        v = I_h(i,j,3);
        %通过将h通道颜色值特定范围内饱和度设为0,保留范围外颜色值
        if h<0.55 || h>0.7  
            I_h(i,j,2) = 0; % 上面已经分析了s=0,会导致灰度化,结果是除了蓝色,其他都是灰色的!!!
        end
    end
end
I_r = hsv2rgb(I_h);
figure, imshow(I_r);

原图片

opencvdrawContours颜色设置透明度_OpenCV_02

蓝色输出,其他是灰度的哈!!!

opencvdrawContours颜色设置透明度_颜色空间_03

3 关于OpenCV的hsv实现

下面就在OpenCV中获取蓝色为例。也可以通过cvSplit完成任务,下面直接访问像素
下面是OpenCV官网关于BGR->HSV的转换公式,以及注意事项 https://docs.opencv.org/3.2.0/de/d25/imgproc_color_conversions.html#color_convert_rgb_hsv

opencvdrawContours颜色设置透明度_OpenCV_04


下面看看几个细节

  1. V和S的范围是0-255,实际上就是unsigned char,或者uchar;其作用和上面是一样的,V=0就是全黑,S=0就是灰度
  2. 最有意思的H,当然H就是控制颜色的,实际上H通道是在六棱锥上定义的,一周即360°,是角度单位,而OpenCV把它除以2,线性转换成0-180,成功装进uchar里。也就是还是角度单位,后面的75没有使用。

为什么要这么做?

  1. 没有必要用两个uchar或者int更大存储范围的数据类型存储
  2. 你可能会想,除以2会不会降低精度,实际上在MATLAB将H转换成0-1的double,所以担心没有必要。
  3. 最重要的是这样直接组成3个uchar,即Vec3b直接和BGR访问像素就通用了,方便了开发。

之后看看OpenCV中H通道和颜色对应关系

不难发现,蓝色对应100-124

opencvdrawContours颜色设置透明度_颜色空间_05

下面,直接通过Vec3b访问HSV空间的像素。

下面的代码和访问BGR是一模一样的,不需要修改,因为OpenCV已经帮你处理好了哈。

cv::Mat src, dst;
	src = cv::imread("hsv.png");
	if (!src.data) {
		cout << "Could't load image." << endl;
		return -1;
	}
	namedWindow("Input image", CV_WINDOW_AUTOSIZE);			//展示输入图片
	cv::imshow("Input image", src);

	cv::cvtColor(src, dst, cv::COLOR_BGR2HSV);				// 转成灰度图片
	int BlueCount = 0;

	Mat out;
	out.create(src.size(), src.type());						// 创建一幅和原图大小相等的空图像
	for (size_t i = 0; i < dst.rows; i++) {
		for (size_t j = 0; j < dst.cols; j++) {
			int h = dst.at<cv::Vec3b>(i, j)(0);
			int s = dst.at<cv::Vec3b>(i, j)(1);
			int v = dst.at<cv::Vec3b>(i, j)(2);
			// 目标:让不是蓝色的灰度显示
			if (!(h > 100 && h < 124)) {
				out.at<cv::Vec3b>(i, j)(1) = 0;
			}
			out.at<cv::Vec3b>(i, j)(0) = h;
			out.at<cv::Vec3b>(i, j)(2) = v;
		}
	}	
	cv::cvtColor(out, out, COLOR_HSV2BGR);
	cv::imshow("out", out);
	cv::waitKey(0);

opencvdrawContours颜色设置透明度_颜色空间_06


下面是绿色,看的更清楚,其他区域是灰度的哈

opencvdrawContours颜色设置透明度_灰度_07