【opencv学习之二十九】彩色分割
程序员文章站
2024-03-24 19:20:52
...
图像的色彩分割其实原理差不多,也是根据图像的rgb色彩组成,设置分割区间来将颜色分开来;比如Scalar(100,100,100)-Scalar(150,150,150)间的色彩分割出来;但是rgb颜色分割时候,rgb值往往不是连续性的,比如下面:
淡蓝色深蓝色啊中间并不递增分布的,所以用rgb彩色分割效果一般,一般采用HSV等方法分割;
代码示例rgb分割:
int img_B,img_G,img_R;
int img_Btop,img_Gtop,img_Rtop;
int img_BMax=255;
int img_GMax=255;
int img_RMax=255;
void callBackBGR(int, void*)
{
Mat img = imread("D:/ImageTest/pic5.png");
Mat mask; //掩码
inRange(img, Scalar(img_B, img_G, img_R), Scalar(img_Btop, img_Gtop, img_Rtop),mask);//可能出现区间负数,但是显示时无bug
//分割
for (int r = 0; r <mask.rows; r++)
{
for (int c = 0; c < mask.cols; c++)
{
if (mask.at<uchar>(r, c) == 255)
{
img.at<cv::Vec3b>(r,c)[0] = 255;//访问第一通道B
img.at<cv::Vec3b>(r,c)[1] = 255;//访问第二通道G
img.at<cv::Vec3b>(r,c)[2] = 255;//访问第三通道R
}
}
}
imshow("dstBGR", mask);
imshow("dstBGR2", img);
}
void coloSegmentation2()//rgb色彩分割
{
Mat img = imread("D:/ImageTest/pic5.png");
imshow("src", img);
namedWindow("dstBGR", WINDOW_KEEPRATIO ); //创建处理窗口
//B
createTrackbar("B", "dstBGR", &img_B, img_BMax, callBackBGR);
createTrackbar("Btop", "dstBGR", &img_Btop, img_BMax, callBackBGR);
//G
createTrackbar("G", "dstBGR", &img_G, img_GMax, callBackBGR);
createTrackbar("Gtop", "dstBGR", &img_Gtop, img_GMax, callBackBGR);
//R
createTrackbar("R", "dstBGR", &img_R, img_RMax, callBackBGR);
createTrackbar("Rtop", "dstBGR", &img_Rtop, img_RMax, callBackBGR);
callBackBGR(0, 0);
waitKey(0);
}
效果:
rgb由于不是连续的所以手动调整滑条时感觉像没什么规律似的,一会这个颜色没了一会全没了;
但是HSV的效果就好多了:
代码示例HSV分割:
//HSV色彩分割
/*
利用inRange函数,通过调节图像颜色信息(H)、饱和度(S)、亮度(V)区间选择我们需要的图像区域
这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,
绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混
合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱
和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最
高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度V
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,
此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
*/
//色相
int hmin = 0;
int hmin_Max = 360;
int hmax = 360;
int hmax_Max = 360;
//饱和度
int smin = 0;
int smin_Max = 255;
int smax = 255;
int smax_Max = 255;
//亮度
int vmin = 106;
int vmin_Max = 255;
int vmax = 250;
int vmax_Max = 255;
//回调函数
void callBack(int, void*)
{
Mat bgr; //灰度值归一化
Mat hsv; //HSV图像
Mat img = imread("D:/ImageTest/pic5.png");
Mat dst = Mat::zeros(img.size(), CV_32FC3); //输出图像分配内存
Mat mask; //掩码
img.convertTo(bgr, CV_32FC3, 1.0 / 255, 0); //彩色图像的灰度值归一化,图像大小没有变化,但是类型UINT8变为了FLOAT32位
cvtColor(bgr, hsv, COLOR_BGR2HSV); //颜色空间转换
inRange(hsv, Scalar(hmin, smin / float(smin_Max), vmin / float(vmin_Max)), Scalar(hmax, smax / float(smax_Max), vmax / float(vmax_Max)), mask);
// void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst );
// src : 第一个原数组
// lower : 下边界数组
// upper : 上边界数组
// dst : 输出数组必须是 8u 或 8s 类型.
// 函数 cvInRange 对输入的数组作范围检查,对于单通道数组:
// dst(I)=lower(I)0 <= src(I)0 < upper(I)0
// 对二通道数组:
// dst(I)=lower(I)0 <= src(I)0 < upper(I)0 &&lower(I)1 <= src(I)1 < upper(I)1
// 如果 src(I) 在范围内dst(I)被设置为 0xff (每一位都是 '1')否则置0 。 除了输出数组所有数组必须是相同的类型相同的大小(或ROI大小)。
//分割
for (int r = 0; r < bgr.rows; r++)
{
for (int c = 0; c < bgr.cols; c++)
{
if (mask.at<uchar>(r, c) == 255)
{
dst.at<Vec3f>(r, c) = bgr.at<Vec3f>(r, c);
}
}
}
imshow("dst", dst);
dst.convertTo(dst, CV_8UC3, 255.0, 0);
// 函数原型
// void Mat::convertTo( Mat& m, int rtype, double alpha=1, double beta=0 )
// const 输入参数;
// m 目标矩阵。如果m的大小与原矩阵不一样,或者数据类型与参数不匹配,那么在函数convertTo内部会先给m重新分配空间。
// rtype 指定从原矩阵进行转换后的数据类型,即目标矩阵m的数据类型。当然,矩阵m的通道数应该与原矩阵一样的。
// 如果rtype是负数,那么m矩阵的数据类型应该与原矩阵一样。
// alpha 缩放因子。默认值是1。即把原矩阵中的每一个元素都乘以alpha。
// beta 增量。默认值是0。即把原矩阵中的每一个元素都乘以alpha,再加上beta。
// 功能
// 把一个矩阵从一种数据类型转换到另一种数据类型,同时可以带上缩放因子和增量,公式如下:
// m(x,y)=saturate_cast<rType>(alpha*(*this)(x,y)+beta);
// 由于有数据类型的转换,所以需要用saturate_cast<rType>来处理数据的溢出。
}
void coloSegmentation()
{
Mat img = imread("D:/ImageTest/pic5.png");
imshow("src", img);
// namedWindow("dst", WINDOW_AUTOSIZE ); //定义输出图像的显示窗口
namedWindow("dst", WINDOW_KEEPRATIO ); //创建处理窗口
//调节色相 H
createTrackbar("hmin", "dst", &hmin, hmin_Max, callBack);
createTrackbar("hmax", "dst", &hmax, hmax_Max, callBack);
//调节饱和度 S
createTrackbar("smin", "dst", &smin, smin_Max, callBack);
createTrackbar("smax", "dst", &smax, smax_Max, callBack);
//调节亮度 V
createTrackbar("vmin", "dst", &vmin, vmin_Max, callBack);
createTrackbar("vmax", "dst", &vmax, vmax_Max, callBack);
callBack(0, 0);
waitKey(0);
}
效果:
比图蓝色暗蓝色绿色这些比较接近的就能连续过滤;
上一篇: 09Condition