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

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

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第1张图片

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第2张图片

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第3张图片

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

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

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第4张图片

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第5张图片

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第6张图片

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

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

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第7张图片

        这时候我们可以选红色下限是(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进行掩码拷贝得到的最终图片,如下: 

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第8张图片

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

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

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第9张图片

        结果如下:

【Emgu.CV教程】第20篇 、色彩处理之InRange()函数进行颜色筛选_第10张图片

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

你可能感兴趣的:(Emgu.CV使用教程,计算机视觉,c#,图像处理,Emgu.CV)