欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-24 19:20:52
...

图像的色彩分割其实原理差不多,也是根据图像的rgb色彩组成,设置分割区间来将颜色分开来;比如Scalar(100,100,100)-Scalar(150,150,150)间的色彩分割出来;但是rgb颜色分割时候,rgb值往往不是连续性的,比如下面:

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

淡蓝色深蓝色啊中间并不递增分布的,所以用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);
}
效果:

【opencv学习之二十九】彩色分割
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);
}
效果:

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

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



上一篇: 09Condition

下一篇: