【Emgu.CV教程】第19篇 、色彩处理之InRange()函数进行颜色筛选

        这篇文章又是偏实战的,读者们拿好小板凳,坐端正了仔细听讲啊。上一篇讲到了不同的颜色空间,为什么会有几十个不同的颜色空间来表示一张图片呢。

        以这张  红叶.jpg 举例,要想提取图片中的树叶,第一眼看到的是什么。

        树叶是红的,而最常用的BGR颜色空间正好代表蓝、绿、红,只需要将 红叶.jpg 进行通道分离,在红色通道内,越亮(越接近255)的必然是红色。 先看一下分离后红色通道是什么样的???

        看到上面结果了吗,基本上白色的部分,就是代表原图中红色区域了,那我再对这个红色通道用一个二值化函数 ,把超过200的部分全部变成白色,其余部分变成黑色,那结果就是下图这样的:

        很明显,在这个二值化图形中,白色区域就是原图中的红色树叶。这不是很简单的就挑出来红色部分了吗??步骤是:

  • 分离BGR颜色空间;
  • 得到红色通道;
  • 二值化红色通道;
  • 得到最终结果。

       这个图是没问题,咱们换一张, 可口可乐.jpg,如下图:

       这个图是以白色为背景,红色为前景的图片。在BGR颜色空间下,它的红色通道是这样的:

       看到了吗,在红色通道中,白色背景比真正红色的还要白。因为白色就是Blue=255、Green=255、Red=255,合并而来。因此在蓝、绿、红三个通道中,都是255。简单的理解,BGR颜色空间下,白色会干扰目标颜色的选择。这就没办法再用二值化函数提取了。此时,就需要进行颜色空间转换了,比如转换成HSV颜色空间,三个通道如下图所示:

        但是接下来怎么提取红色区域呢,InRange()函数闪亮登场。函数定义如下:

public static void InRange(
    IInputArray src,  // 输入图像
    IInputArray lower, // 颜色下限 
    IInputArray upper, // 颜色上限
    IOutputArray dst // 输出图像
)

        它的输出图像是一个二值化图像,可以看成是个掩码图,当输入图像的值在下限和上限之间,掩码图值为255,其余的为0。Emgu.CV中,对HSV的各通道取值范围是:

        这时候我们可以选红色下限是(0,43,46),红色上限是(10,255,255),再应用InRange(),全部代码如下:

Mat hsvMat = new Mat();
Mat maskMat = new Mat();
Mat tempMat = srcMat.Clone();
CvInvoke.CvtColor(tempMat, hsvMat, Emgu.CV.CvEnum.ColorConversion.Bgr2Hsv);
Mat[] channels = hsvMat.Split();
CvInvoke.Imshow("HSV H channel, " + channels[0].Size.ToString(), channels[0]);
CvInvoke.Imshow("HSV S channel, " + channels[1].Size.ToString(), channels[1]);
CvInvoke.Imshow("HSV V channel, " + channels[2].Size.ToString(), channels[2]);

// 定义红色的上下限
double hMin = 0, sMin = 43, vMin = 46;
double hMax = 10, sMax = 255, vMax = 255;
ScalarArray hsvMin = new ScalarArray(new MCvScalar(hMin, sMin, vMin));
ScalarArray hsvMax = new ScalarArray(new MCvScalar(hMax, sMax, vMax));
CvInvoke.InRange(hsvMat, hsvMin, hsvMax, maskMat); // 输出为符合要求的掩码图
CvInvoke.Imshow("Red mask, " + maskMat.Size.ToString(), maskMat);

// 提取红色区域并拷贝到黑底的图片上
Mat black = Mat.Ones(srcMat.Rows, srcMat.Cols, DepthType.Cv8U, 3);
tempMat.CopyTo(black, maskMat);
CvInvoke.Imshow("Final image only red, " + black.Size.ToString(), black);

        利用InRange()函数得到的maskMat掩码图和利用maskMat进行掩码拷贝得到的最终图片,如下: 

        InRange()函数要多做试验,小提示:这几篇都是介绍色彩处理的,选择图片时,一定要选颜色丰富的,才能突出效果。 

        代码不变,换成这张彩图试一试:

        结果如下:

原创不易,请勿抄袭。共同进步,相互学习。 

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2023-12-29 09:54:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-29 09:54:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-29 09:54:05       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-29 09:54:05       20 阅读

热门阅读

  1. P2440 木材加工

    2023-12-29 09:54:05       48 阅读
  2. 服务器通常不使用图形化界面的原因

    2023-12-29 09:54:05       38 阅读
  3. catboost回归自动调参

    2023-12-29 09:54:05       29 阅读
  4. 7天玩转 Golang 标准库之 sort

    2023-12-29 09:54:05       37 阅读
  5. 多线程多进程的使用场景和常见问题处理

    2023-12-29 09:54:05       40 阅读
  6. MySQL数据库索引

    2023-12-29 09:54:05       37 阅读
  7. Presentation Error:编程中的细节之战

    2023-12-29 09:54:05       32 阅读
  8. 获取请求的真实ip

    2023-12-29 09:54:05       37 阅读