我参考了一篇文章,还很好,链接 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);原图片
蓝色输出,其他是灰度的哈!!!
下面就在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);下面是绿色,看的更清楚,其他区域是灰度的哈