简谈HSV颜色空间,MATLAB和OpenCV实现

tech2025-09-16  14

目录

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

1 HSV颜色空间

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

2 关于Matlab的hsv实现

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

在这里,我选取了蓝色,根据上图选择了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);

原图片

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

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

下面看看几个细节

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

为什么要这么做?

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

之后看看OpenCV中H通道和颜色对应关系 不难发现,蓝色对应100-124

下面,直接通过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);

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

最新回复(0)