【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()函数要多做试验,小提示:这几篇都是介绍色彩处理的,选择图片时,一定要选颜色丰富的,才能突出效果。?
? ? ? ? 代码不变,换成这张彩图试一试:
? ? ? ? 结果如下:
原创不易,请勿抄袭。共同进步,相互学习。?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!