【opencv学习之二十九】彩色分割

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abcvincent/article/details/79256059

图像的色彩分割其实原理差不多,也是根据图像的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);
}
效果:


比图蓝色暗蓝色绿色这些比较接近的就能连续过滤;



猜你喜欢

转载自blog.csdn.net/abcvincent/article/details/79256059