zoukankan      html  css  js  c++  java
  • opencv 彩色图像分割(inrange)

      灰度图像大多通过算子寻找边缘和区域生长融合来分割图像。

      彩色图像增加了色彩信息,可以通过不同的色彩值来分割图像,常用彩色空间HSV/HSI, RGB, LAB等都可以用于分割!

      笔者主要介绍inrange() 来划分颜色区域。先看看OpenCV的文档:

      C++: void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)

      C: void cvInRangeS(const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst) 

    • src – first input array.
    • lowerb – inclusive lower boundary array or a scalar.
    • upperb – inclusive upper boundary array or a scalar.
    • dst – output array of the same size as src and CV_8U type
    • For two-channel arrays:

      	exttt{dst} (I)= 	exttt{lowerb} (I)_0  leq 	exttt{src} (I)_0 leq  	exttt{upperb} (I)_0  land 	exttt{lowerb} (I)_1  leq 	exttt{src} (I)_1 leq  	exttt{upperb} (I)_1

    • and so forth.

      意思主要是:

      src:输入图像,CV2常用Mat类型;

      lowerb:lower boundary下限,scalar类型的像素值,单通道scalar取一个值就行,彩图3通道scalar三个值;

      upperb:上限,类型与lowerb同理;

      dst:输出图像,尺寸与src一致,类型是CV_8U,但没有指定通道数。

      对于多通道的输入,输出结果是各个通道的结果相与,当各通道结果都在上下限之内时,输出为255,否则为0。因此也有人将输出理解为掩码模板!

      看个例子吧:  

     1 int hmax = 360;
     2 int hmax_Max = 360;
     3 //饱和度  
     4 int smin = 0;
     5 int smin_Max = 255;
     6 int smax = 255;
     7 int smax_Max = 255;
     8 //亮度  
     9 int vmin = 106;
    10 int vmin_Max = 255;
    11 int vmax = 250;
    12 int vmax_Max = 255;
    13 //显示原图的窗口  
    14 string windowName = "src";
    15 //输出图像的显示窗口  
    16 string dstName = "dst";
    17 //输出图像  
    18 Mat dst;
    19 //回调函数  
    20 void callBack(int, void*)
    21 {
    22     //输出图像分配内存  
    23     dst = Mat::zeros(img.size(), CV_32FC3);
    24     //掩码  
    25     Mat mask;
    26     inRange(hsv, Scalar(hmin, smin / float(smin_Max), vmin / float(vmin_Max)), Scalar(hmax, smax / float(smax_Max), vmax / float(vmax_Max)), mask);
    27     //只保留  
    28     for (int r = 0; r < bgr.rows; r++)
    29     {
    30         for (int c = 0; c < bgr.cols; c++)
    31         {
    32             if (mask.at<uchar>(r, c) == 255)
    33             {
    34                 dst.at<Vec3f>(r, c) = bgr.at<Vec3f>(r, c);
    35             }
    36         }
    37     }
    38     //输出图像  
    39     imshow(dstName, dst);
    40     //保存图像  
    41     dst.convertTo(dst, CV_8UC3, 255.0, 0);
    42     imwrite("HSV_inRange.jpg", dst);
    43 }
    44 void test_main()
    45 {
    46     //输入图像  
    47     img = imread("E:\素材图片\1.png",1);
    48     if (!img.data || img.channels() != 3)
    49         return ;
    50     imshow(windowName, img);
    51     //彩色图像的灰度值归一化  
    52     img.convertTo(bgr, CV_32FC3, 1.0 / 255, 0);
    53     //颜色空间转换  
    54     cvtColor(bgr, hsv, COLOR_BGR2HSV);
    55     //定义输出图像的显示窗口  
    56     namedWindow(dstName, WINDOW_NORMAL);
    57     //调节色相 H  
    58     createTrackbar("hmin", dstName, &hmin, hmin_Max, callBack);
    59     createTrackbar("hmax", dstName, &hmax, hmax_Max, callBack);
    60     //调节饱和度 S  
    61     createTrackbar("smin", dstName, &smin, smin_Max, callBack);
    62     createTrackbar("smax", dstName, &smax, smax_Max, callBack);
    63     //调节亮度 V  
    64     createTrackbar("vmin", dstName, &vmin, vmin_Max, callBack);
    65     createTrackbar("vmax", dstName, &vmax, vmax_Max, callBack);
    66     callBack(0, 0);
    67     waitKey(0);
    68     return;
    69 }

      函数外的为全局变量,头文件自己加上就行。

      放两张不同的图片分割结果:

        

      第一种是通过调节H值将红色和绿色分割开,SV的值我选择保持默认。(忽略结果图右下角的输入法。。。)

          

      第二种调节H值并没有什么改善,但是可以调节S饱和度,将车牌前景和背景对比的更加强烈。(忽略结果图右下角的输入法。。。)

      更多调节策略欢迎大家评价~~

    附上完整可运行代码路径,还是不能运行的注意 readme。 https://github.com/chenzhefan/inrange_color

  • 相关阅读:
    07 监控100台服务器磁盘利用率
    算法提高 阮小二买彩票
    算法提高 日期计算
    算法提高 身份证号码升级
    算法提高 统计单词数
    算法提高 3000米排名预测
    算法提高 最长字符序列
    算法提高 种树
    算法训练 装箱问题
    算法训练 瓷砖铺放
  • 原文地址:https://www.cnblogs.com/chenzhefan/p/7648433.html
Copyright © 2011-2022 走看看