基于hsv颜色空间的图像分割原理以及实现
HSV颜色空间模型是倒锥形模型:
这个模型是按色调(Hue)、饱和度(Saturation)、明暗(Value)来描述的。
H值代表色调、S值代表饱和度、V值代表亮度。
在圆锥上,角度代表色调H,饱和度S表示为点到中心竖线的距离,而亮度值V用中心竖线表示。
可以理解为:以圆锥底面圆心出发,沿着半径所在直线走越走色彩越鲜艳(S越大)。沿这当前点所在同心圆旋转则代表颜色改变(V改变),沿这母线往下则越大明暗程度越暗(V变大)
HSV对用户来说是一种直观的颜色模型。我们可以从一种纯彩色开始,即指定彩色角H,并让V=S=1,然后我们就可以通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小v而s不变,同样增加白色可以减小S而V不变。例如,要想得到深蓝色,V=0.4 S=1 H=240,要想得到淡蓝色,V=1 S=0.4 H=240.
HSV在用于指定颜色分割时,有比较大的作用。
因为,一般同类事物的颜色一般相同/相近。所以,当所求对象颜色稳定,且其他干扰项没有相似颜色/有相似颜色不过区域面积小,就可以通过颜色HSV色彩空间来将这个对象提取出来。
很好,很有精神!这样理论完备,下面“魔法”开始!
注:跑的程序配置:VS2019,Opencv4.
opencv环境配置可以看这个视频:
https://www.bilibili.com/video/BV1i54y1m7tw?p=1
一、在知道目标对象颜色的HSV最小阀值和最大阀值的情况下如何在图像中标注出来?
功能:将颜色在h ( 91 ~91),s(255 ~ 255),v(203 ~203)这一色彩空间的图像用白色显示出来。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
int hmin = 91, smin = 255, vmin = 203;
int hmax = 91, smax = 255, vmax = 203;
Mat imgHSV, Mask;
Mat image = imread("D:/imagic/shapes.png");
cvtColor(image, imgHSV, COLOR_BGR2HSV);//映射到HSV色彩空间
Scalar lower(hmin, smin, vmin);//得到色彩空间的最小阀值
Scalar upper(hmax, smax, vmax);//得到色彩空间的最大阀值
inRange(imgHSV, lower, upper, Mask);//在这一空间内的显示白色,否则显示黑色并保存在Mask里面。
imshow("image HSV", imgHSV);
imshow("image Mask", Mask);
waitKey(0);
return 0;
}
可是很多时候,我们是不知道对象具体所属的色彩空间范围到底是多少的,这就需要我们去测了。测试方法如下:
二、对图片中物体HSV色彩空间范围测试。
调节方法:
1、从第一行往下依次调。
2、min的就往右调大,max往左调小。
3、这一滑动条,调整到恰当位置现象是,移动到该点时候如果(min调大一点/max调小一点),那目标对象/图片就从白色变为黑色(表示颜色区间排除了这个颜色)那么这行就算调好了。
图示:
那么hmin=91就是最合适的,下一行是hmax,我们开始调hmax
很明显,hmax=91时候也是最好的,就这样一行行调过去,就得到hmin,hmax,smin,smax,vmin,vmax,这六个参数了。
得到之后,用法就跟上面一样,可以在图片中直接显示出这个图像
以下是提取照片中的三角形栗子:
功能:
创建6个createTrackbar()滑动条分别代表hmin,hmax,smin,smax,vmin,vmax。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
int hmin = 0, smin = 0, vmin = 0;
int hmax = 179, smax = 255, vmax = 255;
Mat imgHSV, Mask;
Mat image = imread("下面那个图片的地址");
namedWindow("Trackbars", (600, 200));
createTrackbar("Hue Min", "Trackbars", &hmin, 179);//创建createTrackbar
createTrackbar("Hue Max", "Trackbars", &hmax, 179);
//从左到右分别代bar也就是滑动条的名字,滑动条在哪一个窗口,滑动条指的值就是&hmax的值动态修改,最大上限是179
createTrackbar("Sat Min", "Trackbars", &smin, 255);
createTrackbar("Sat Max", "Trackbars", &smax, 255);
createTrackbar("Val Min", "Trackbars", &vmin, 255);
createTrackbar("Val Max", "Trackbars", &vmax, 255);
cvtColor(image, imgHSV, COLOR_BGR2HSV);//映射到HSV空间
while (true)
{
Scalar lower(hmin, smin, vmin);
Scalar upper(hmax, smax, vmax);
inRange(imgHSV, lower, upper, Mask);//获取涂层蒙版
imshow("image HSV", imgHSV);
imshow("image Mask", Mask);
waitKey(1);
}
return 0;
}
测试图片:
三、视频/相机的单个物体颜色提取
test.code功能:
如果是笔记本输入0,打开内置摄像头。
将想要识别的物体图像放到相机前,然后用类似获取单个图像中目标对象的最大最小阀值的方法,获取视频中物体的hmin,hmax,smin,smax,vmin,vmax。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
int num;
cout << "please cin the number thar you want to test the VideoCaptureNumuber" << endl;
cout << "如果你有内置摄像机比如是笔记本那么就输入0,否则如果是连接了外置摄像机请输入1" << endl;
cin >> num;
Mat imgHSV, Mask, image;
VideoCapture capture(num);
int hmin = 0, smin = 0, vmin = 0;
int hmax = 178, smax = 255, vmax = 255;
namedWindow("Trackbars", (600, 200));
createTrackbar("Hue Min", "Trackbars", &hmin, 179);
createTrackbar("Hue Max", "Trackbars", &hmax, 179);
createTrackbar("Sat Min", "Trackbars", &smin, 255);
createTrackbar("Sat Max", "Trackbars", &smax, 255);
createTrackbar("Val Min", "Trackbars", &vmin, 255);
createTrackbar("Val Max", "Trackbars", &vmax, 255);
while (true)
{
capture >> image;
flip(image, image, 1);
cvtColor(image, imgHSV, COLOR_BGR2HSV);
Scalar lower(hmin, smin, vmin);
Scalar upper(hmax, smax, vmax);
inRange(imgHSV, lower, upper, Mask);//获取涂层蒙版
//cout << hmin << "," << smin << "," << vmin << "," << hmax << "," << smax << "," << vmax << endl;
imshow("image", image);
//imshow("image HSV", imgHSV);
imshow("image Mask", Mask);
waitKey(1);
}
capture.release();
}
四、视频/相机的多个物体颜色提取出来后并保存的方法
未完待续~~~最迟今天或明天更新