本文作者:小嗷
微信公众号:aoxiaoji
吹比QQ群:736854977
image image image
在第5篇阈值threshold函数和第29篇用到adaptiveThreshold二值化
这应该是阈值的最后一篇
在本篇中,您将学习:
-
使用OpenCV cv::inRange函数执行基本阈值操作。()
-
根据HSV颜色空间中像素值的范围检测一个对象。
本文你会找到以下问题的答案:
-
inRange()
-
cvtColor()
-
iostream()
-
max()与min()
2.1 原理
-
在前几篇中,我们学习了如何使用cv::阈值函数来执行阈值。(第5篇和第29篇)
-
在本篇中,我们将学习如何使用cv::inRange函数。
-
这个概念仍然是一样的(和第5篇),但是现在我们添加了我们需要的一系列像素值。
2.2 HSV 彩色空间
HSV(色相、饱和度、值)色彩空间是一种代表色彩空间的模型,类似于RGB颜色模型。由于色彩通道为颜色类型建模,所以它在图像处理任务中非常有用,因为它需要根据颜色来分割对象。饱和度的变化从不饱和到表示灰色和完全饱和(没有白色成分)。Value channel描述颜色的亮度或强度。下一个图像显示HSV圆柱。
image.gif通过sharkd派生作品:SharkD CC By sa 3.0或GFDL,通过维基共享(图源维基百科)
(说明一下Hue是色彩的意思,Saturation是饱和度,Value代表是亮度)
由于RGB颜色空间中的颜色是使用三个通道进行编码的,所以在图像中根据其颜色对一个对象进行分段是比较困难的。
image由SharkD GFDL或CC By sa 4.0,来自维基共享(图源维基百科)
用于从一个颜色空间转换到另一个颜色空间的公式是:cv::cvtColor函数
HSL and HSV来自维基百科详解
https://en.wikipedia.org/wiki/HSLandHSV
image3.1 inRange()
检查数组元素是否位于两个其他数组的元素之间。
1void cv::inRange ( InputArray src, 2 InputArray lowerb, 3 InputArray upperb, 4 OutputArray dst 5 )
这个函数检查范围如下:
对于单通道输入阵列的每一个元素:
image双通道数组:
image等等
也就是说,如果src(I)在指定的1D、2D、3D中,那么dst(I)被设置为255(所有1位)。其余都是0。
当下界和/或上界参数为标量(固定不变的数值)时,在上面的公式中,下标(I)和上b的索引应该被省略。
参数详解:
-
src:输入图像,CV2常用Mat类型;
-
lowerb:具有包容性的下界数组或标量。
-
upperb:包含上边界数组或标量。
-
dst:与src和cv8u类型相同大小的输出阵列。(CV8U忘了是什么的小伙伴请回到第21篇,即图像深度0-255,0-255就是)
inRange()好处及用法:可以同时针对多通道进行操作,每个通道的像素值都必须在规定的阈值范围内!
(什么操作?这个像素值不得超过最低值lowerb,和最大值upperb,超过就黑色,没有就白色。小学数学题,忘了小嗷也没办法)
阈值就是单纯的大于小于,inrange则是既要小于它又要大于他
3.2 cvtColor()
将图像从一个颜色空间转换为另一个颜色空间。
1void cv::cvtColor ( InputArray src, 2 OutputArray dst, 3 int code, 4 int dstCn = 0 5 )
该函数将输入图像从一个颜色空间转换为另一个颜色空间。如果转换到RGB颜色空间,通道的顺序应该显式地指定(RGB或BGR)。注意,OpenCV中的默认颜色格式通常被称为RGB,但它实际上是BGR(字节被颠倒了)。因此,标准(24位)颜色图像中的第一个字节将是一个8位的蓝色组件,第二个字节将是绿色的,第三个字节将是红色的。(8位就是2的8次方等于255,这里说的专业点)
R、G和B通道值的常规范围是:
-
cv8u图像的0到255
-
对于cv16u图像,0到65535
-
cv32f图像的0到1
在线性变换的情况下,这个范围并不重要。但是,在非线性转换的情况下,输入RGB图像应该被规范化为适当的值范围,以获得正确的结果,例如,
RGB到Luv变换。例如,如果您有一个32位的浮点图像直接从8位图像转换而没有任何缩放,那么它就会有0。255的值范围而不是0。由函数承担。因此,在调用cvtColor之前,您首先需要将图像缩小:
img *= 1./255;
cvtColor(img, img, COLOR_BGR2Luv);
如果您使用带有8位图像的cvtColor,那么转换将会丢失一些信息。对于许多应用程序来说,这是不明显的,但是建议在应用程序中使用32位图像,这些应用程序需要全部的颜色,或者在操作之前转换图像,然后再转换回来。
如果转换增加了alpha通道,它的值将被设置为对应的通道范围的最大值:cv8u的255,cv16u的65535,cv32f的1。
参数详解:
-
src:输入图像为8位无符号,16位无符号(cv16uc。)或单精度浮点。
-
dst:与src相同大小和深度的输出图像。
-
code:彩色空间转换代码(参见colorconversioncode)。
-
dstCn:目标图像中的通道数;如果参数为0,则通道的数量将自动从src和代码中派生出来。(原来深度)
其中,最后一个参数dstCn用于指定目标图像的通道数,如果指定的值是默认值0,那么通道数将由输入图像和颜色转换码决定。 cv::cvtColor()支持多种颜色空间之间的转换,其支持的转换类型和转换码如下:
1、RGB和BGR(opencv默认的彩色图像的颜色空间是BGR)颜色空间的转换
cv::COLORBGR2RGB cv::COLORRGB2BGR cv::COLORRGBA2BGRA cv::COLORBGRA2RGBA
2、向RGB和BGR图像中增添alpha通道
cv::COLORRGB2RGBA cv::COLORBGR2BGRA
3、从RGB和BGR图像中去除alpha通道
cv::COLORRGBA2RGB cv::COLORBGRA2BGR
4、从RBG和BGR颜色空间转换到灰度空间
cv::COLORRGB2GRAY cv::COLORBGR2GRAY
cv::COLORRGBA2GRAY cv::COLORBGRA2GRAY
5、从灰度空间转换到RGB和BGR颜色空间
cv::COLORGRAY2RGB cv::COLORGRAY2BGR
cv::COLORGRAY2RGBA cv::COLORGRAY2BGRA
6、RGB和BGR颜色空间与BGR565颜色空间之间的转换
cv::COLORRGB2BGR565 cv::COLORBGR2BGR565 cv::COLORBGR5652RGB cv::COLORBGR5652BGR cv::COLORRGBA2BGR565 cv::COLORBGRA2BGR565 cv::COLORBGR5652RGBA cv::COLORBGR5652BGRA
7、灰度空间域BGR565之间的转换
cv::COLORGRAY2BGR555 cv::COLORBGR5552GRAY
8、RGB和BGR颜色空间与CIE XYZ之间的转换
cv::COLORRGB2XYZ cv::COLORBGR2XYZ cv::COLORXYZ2RGB cv::COLORXYZ2BGR
9、RGB和BGR颜色空间与uma色度(YCrCb空间)之间的转换
cv::COLORRGB2YCrCb cv::COLORBGR2YCrCb cv::COLORYCrCb2RGB cv::COLORYCrCb2BGR
10、RGB和BGR颜色空间与HSV颜色空间之间的相互转换
cv::COLORRGB2HSV cv::COLORBGR2HSV cv::COLORHSV2RGB cv::COLORHSV2BGR
11、RGB和BGR颜色空间与HLS颜色空间之间的相互转换
cv::COLORRGB2HLS cv::COLORBGR2HLS cv::COLORHLS2RGB cv::COLORHLS2BGR
12、RGB和BGR颜色空间与CIE Lab颜色空间之间的相互转换
cv::COLORRGB2Lab cv::COLORBGR2Lab cv::COLORLab2RGB cv::COLORLab2BGR
13、RGB和BGR颜色空间与CIE Luv颜色空间之间的相互转换
cv::COLORRGB2Luv cv::COLORBGR2Luv cv::COLORLuv2RGB cv::COLORLuv2BGR
14、Bayer格式(raw data)向RGB或BGR颜色空间的转换
cv::COLORBayerBG2RGB cv::COLORBayerGB2RGB cv::COLORBayerRG2RGB cv::COLORBayerGR2RGB cv::COLORBayerBG2BGR cv::COLORBayerGB2BGR cv::COLORBayerRG2BGR cv::COLORBayerGR2BGR
image线性变换也成为线性映射( linear mapping),是从一个向量空间V到另一个向量空间W的映射且保持加法运算和数量乘法运算,而线性变换(linear transformation)是线性空间V到其自身的线性映射。(小嗷以后抽点时间写写,这里简单说说)
LUV色彩空间全称CIE 1976(L,u,v) (也作CIELUV)色彩空间,L表示物体亮度,u和v是色度。于1976年由国际照明委员会CIE 提出,由CIE XYZ空间经简单变换得到,具视觉统一性。类似的色彩空间有CIELAB。对于一般的图像,u和v的取值范围为-100到+100,亮度为0到100。
3.3 iostream
iostream是指iostream库
3.4 min()与max()
1softfloat cv::min(max) ( const softfloat & a, 2 const softfloat & b 3 )
max(a, b) 表示a,b中较大的数 当a>b时,值为a。 当a<b时,值为b。
min()则相反,不懂的话.QQ叫小嗷。
image本篇文章的代码如下所示。
1//首先是包含的包(类),1包含.图像处理,那么一定是imgproc.hpp 2//然后,需要图行界面那么就是:highgui 3//基本的输入输出流 4 5#include "opencv2/imgproc.hpp" 6#include "opencv2/highgui.hpp" 7#include <iostream> 8 9//命名控件10using namespace cv;11//色彩18012const int max_value_H = 360 / 2;13const int max_value = 255;14const String window_capture_name = "Video Capture";//打开摄像头的窗口名字15const String window_detection_name = "Object Detection";//侦察窗口名字16int low_H = 0, low_S = 0, low_V = 0;17int high_H = max_value_H, high_S = max_value, high_V = max_value;181920//定义回调函数,轨迹条21static void on_low_H_thresh_trackbar(int, void *)22{23 low_H = min(high_H - 1, low_H);24 setTrackbarPos("Low H", window_detection_name, low_H);25}2627static void on_high_H_thresh_trackbar(int, void *)28{29 high_H = max(high_H, low_H + 1);30 setTrackbarPos("High H", window_detection_name, high_H);31}3233static void on_low_S_thresh_trackbar(int, void *)34{35 low_S = min(high_S - 1, low_S);36 setTrackbarPos("Low S", window_detection_name, low_S);37}3839static void on_high_S_thresh_trackbar(int, void *)40{41 high_S = max(high_S, low_S + 1);42 setTrackbarPos("High S", window_detection_name, high_S);43}4445static void on_low_V_thresh_trackbar(int, void *)46{47 low_V = min(high_V - 1, low_V);48 setTrackbarPos("Low V", window_detection_name, low_V);49}5051static void on_high_V_thresh_trackbar(int, void *)52{53 high_V = max(high_V, low_V + 1);54 setTrackbarPos("High V", window_detection_name, high_V);55}5657int main(int argc, char* argv[])58{59 VideoCapture cap(argc > 1 ? atoi(argv[1]) : 0);6061 namedWindow(window_capture_name);62 namedWindow(window_detection_name);6364 // Trackbars to set thresholds for HSV values65 createTrackbar("Low H", window_detection_name, &low_H, max_value_H, on_low_H_thresh_trackbar);66 createTrackbar("High H", window_detection_name, &high_H, max_value_H, on_high_H_thresh_trackbar);67 createTrackbar("Low S", window_detection_name, &low_S, max_value, on_low_S_thresh_trackbar);68 createTrackbar("High S", window_detection_name, &high_S, max_value, on_high_S_thresh_trackbar);69 createTrackbar("Low V", window_detection_name, &low_V, max_value, on_low_V_thresh_trackbar);70 createTrackbar("High V", window_detection_name, &high_V, max_value, on_high_V_thresh_trackbar);7172 Mat frame, frame_HSV, frame_threshold;73 while (true) {74 cap >> frame;75 if (frame.empty())76 {77 break;78 }7980 // Convert from BGR to HSV colorspace81 cvtColor(frame, frame_HSV, COLOR_BGR2HSV);82 // Detect the object based on HSV Range Values83 inRange(frame_HSV, Scalar(low_H, low_S, low_V), Scalar(high_H, high_S, high_V), frame_threshold);8485 // Show the frames86 imshow(window_capture_name, frame);87 imshow(window_detection_name, frame_threshold);8889 char key = (char)waitKey(30);90 if (key == 'q' || key == 27)91 {92 break;93 }94 }95 return 0;96}
结果:
在编译完这个程序之后,运行它。这个程序将打开两个窗口
当您从trackbar中设定范围值时,得到的帧将在另一个窗口中可见。
image即:同时设置多个通道范围范围大小(Hue是色彩的意思,Saturation是饱和度,Value代表是亮度)
色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度V
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
小嗷的米黄色衣服
image image因为光线的影响,所以得到的效果不满意
解释一下:
让我们来看看这个项目的总体结构:
- 从默认的或提供的捕获设备中捕获视频流。
1 VideoCapture cap(argc > 1 ? atoi(argv[1]) : 0);
- 创建一个窗口来显示默认框架和阈值框架。
1 namedWindow(window_capture_name);2 namedWindow(window_detection_name);
- 创建跟踪条来设置HSV值的范围
1 // Trackbars to set thresholds for HSV values2 createTrackbar("Low H", window_detection_name, &low_H, max_value_H, on_low_H_thresh_trackbar);3 createTrackbar("High H", window_detection_name, &high_H, max_value_H, on_high_H_thresh_trackbar);4 createTrackbar("Low S", window_detection_name, &low_S, max_value, on_low_S_thresh_trackbar);5 createTrackbar("High S", window_detection_name, &high_S, max_value, on_high_S_thresh_trackbar);6 createTrackbar("Low V", window_detection_name, &low_V, max_value, on_low_V_thresh_trackbar);7 createTrackbar("High V", window_detection_name, &high_V, max_value, on_high_V_thresh_trackbar);
- 在用户希望程序退出之前,执行以下操作
1 cap >> frame; 2 if(frame.empty()) 3 { 4 break; 5 } 6 7 // Convert from BGR to HSV colorspace 8 cvtColor(frame, frame_HSV, COLOR_BGR2HSV); 9 // Detect the object based on HSV Range Values10 inRange(frame_HSV, Scalar(low_H, low_S, low_V), Scalar(high_H, high_S, high_V), frame_threshold);
- 显示的图像
1 // Show the frames2 imshow(window_capture_name, frame);3 imshow(window_detection_name, frame_threshold);
- 对于一个控制较低范围的轨迹条,比如色相值:(最低不能低于)
1 static void on_low_H_thresh_trackbar(int, void *) 2 { 3 low_H = min(high_H-1, low_H); 4 setTrackbarPos("Low H", window_detection_name, low_H); 5 } 6 7 static void on_low_H_thresh_trackbar(int, void *) 8 { 9 low_H = min(high_H-1, low_H);10 setTrackbarPos("Low H", window_detection_name, low_H);11 }
- 对于一个控制上范围的轨迹条,比如色相值:(最大不能大于)
1 static void on_high_H_thresh_trackbar(int, void *)2 {3 high_H = max(high_H, low_H+1);4 setTrackbarPos("High H", window_detection_name, high_H);5 }
有必要找出最大和最小值,以避免差异,例如阈值的高值小于低值。
image.gif-
本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)
-
大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年
-
写文章主要是为了后人少走点弯路,多交点朋友,一起学习
-
如果有好的图像识别群拉我进去QQ:631821577
-
就我一个白板,最后还是成的,你们别怕,慢慢来吧
分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。
邮箱:631821577@qq.com
QQ群:736854977
有什么疑问公众号提问,下班或者周六日回答,ths
感言
嗷嗷嗷~~~,喜欢就推荐一下好友
上次的小伙伴问我怎么滤波,只留黄色部分的图像。小嗷周六日试试的效果和代码如下
image在CamfhiftDemo窗口中左键长按拉到你想要的区域,松手 -> 自动获取选中区域色彩直方图 -> 移动就跟着走(实际受到环境因素的影响,效果不怎么好,不同于软件生成图。),代码在本篇百度云链接上,
image image推荐文章:
没有
代码链接:
https://pan.baidu.com/s/1K-d1lr9KsY9jCXAq9WvC1g
密码:e3vf
小嗷
image
网友评论