【Emgu CV教程】3.2、色彩处理之灰度图

本文介绍了如何使用EmguCV将BGR彩色图像转换为灰度图,包括CvtColor()函数的应用、不同灰度化算法(如平均值、加权平均)以及Decolor()函数的优势。同时提到灰度图在图像处理中的优势,如减少计算量和便于特征提取。
摘要由CSDN通过智能技术生成

我们看到的彩色图像,一般都是BGR颜色空间的,也就是一副图像,是由蓝色通道、绿色通道、红色通道组合而成。而灰度图只有一个通道,他有256个灰度等级,255代表全白,0表示全黑。

注意啊,下面这副黑白图像,利用Emgu CV的默认方式读取的时候,可不是灰度图,而是BGR格式的彩色图片。

读取过程如下,您看是不是个三通道的BGR颜色空间图片,这个时候要是遍历srcMat的所有像素点,您会发现它每个像素点上三个通道的值是相同的。它其实可以看成是三个完全相同的灰度图组成。

记住:灰度图是单通道、彩色图片是三通道,不是黑白色的图像就是灰度图。

那要怎么把Emgu CV的读取的图片转成灰度图呢?下面以  lena.jpg 举例。

1、CvtColor()转灰度图

可以使用CvtColor(),官方介绍如下:

public static void CvtColor(
    IInputArray src, // 输入图像
    IOutputArray dst, // 输出图像
    ColorConversion code, // 颜色空间转换代码
    int dstCn = 0 // 输出图像的通道数,默认值为 0,可以不写
)

这个函数就是完成颜色空间转换,功能非常强大,当BGR转灰度图时,要选择 ColorConversion.Bgr2Gray,使用方式如下:

Mat dstMat = srcMat.Clone();
CvInvoke.CvtColor(dstMat, dstMat, ColorConversion.Bgr2Gray);
CvInvoke.Imshow("CvtColor gray Mat, " + dstMat.Size.ToString(), dstMat);

lena.jpg转成灰度图的效果如下:

2、更进一步的背景知识

其实是我从网上搜集到的,BGR转灰度图,是有很多算法的。使用不同的算法,得到的灰度图结果也不一样,比如:

  • 平均值法:Gray = (Red + Green + Blue) / 3
  • 最大灰度值法:Gray = Max(Red, Green, Blue) 
  • 最小灰度值法:Gray = Max(Red, Green, Blue) 
  • 加权平均 - - 浮点处理法:Gray = (Red * 0.299 + Green * 0.587 + Blue * 0.114)
  • 加权平均 - - 整数处理法:Gray = (Red * 30 + Green * 59 + Blue * 11) / 100

Emgu CV里的CvtColor()函数,更准确的说是OpenCV里的CvtColor()函数采用的是什么算法,我也不知道。读者与兴趣可以去github上研究研究。

3、Decolor()脱色处理

这个介绍的不多哈,读者们赚了。彩色图片转灰度图时,除了用最常见的CvtColor()函数以外,还有一个Decolor()函数,与CvtColor()函数相比,更能保持原始图像的颜色对比度。这个算法更加复杂,该代码是源于香港中文大学计算机科学与工程系的一篇论文 ,链接地址如下:

Contrast Preserving Decolorization

不想研究源码的读者,直接看下面的使用方法:

Mat tempMat = srcMat.Clone();
Mat dstMat1 = new Mat();
Mat dstMat2 = new Mat();
Mat colorBoostMat = new Mat();
CvInvoke.Decolor(tempMat, dstMat1, colorBoostMat);
CvInvoke.CvtColor(tempMat, dstMat2, ColorConversion.Bgr2Gray);
CvInvoke.Imshow("Decolor() gray Mat, " + dstMat1.Size.ToString(), dstMat1);
CvInvoke.Imshow("Decolor() color boost Mat, " + colorBoostMat.Size.ToString(), colorBoostMat);
CvInvoke.Imshow("CvtColor gray Mat, " + dstMat2.Size.ToString(), dstMat2);

原始图片srcMat、Decolor()脱色后的灰度图、CvtColor()直接转换的灰度图如下:

可以看到,Decolor()脱色后的灰度图明暗对比要更明显一些。这个函数比较适合这种透雾处理的图片,但是运算速度要明显比CvtColor()函数慢很多,一般情况下还是选择用CvtColor()函数。

4、手搓算法转灰度图

据说是采用 加权平均更符合人眼的视觉效果,而且整数法又要快于浮点法。那接下来我们自己也可以写一个算法,试一试把BGR图像转灰度图:

int width = srcMat.Cols;
int height = srcMat.Rows;
Mat dstMat = new Mat(new System.Drawing.Size(width, height), DepthType.Cv8U, 1);
Mat tempMat = srcMat.Clone();
Image<Gray, int> dstImage = new Image<Gray, int>(width, height);
Image<Bgr, int> tempImage = tempMat.ToImage<Bgr, int>();
for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; ++j)
    {
        dstImage.Data[i, j, 0] = ((11 * tempImage.Data[i, j, 0]) + (59 * tempImage.Data[i, j, 1]) + (30 * tempImage.Data[i, j, 2])) / 100;
    }
}

dstMat = dstImage.Mat;
dstMat.ConvertTo(dstMat, DepthType.Cv8U);
CvInvoke.Imshow("Custom function gray Mat, " + dstMat.Size.ToString(), dstMat);

转换后的lena.jpg如下图:

将lena.jpg转灰度图时,用Emgu CV的CvtColor()函数用时0.012秒,手搓的算法用时0.019秒,慢差不多0.007秒,如果使用C++配合OpenCV应该更快。看到了吧,差距不小,为什么OpenCV这么流行,人家是有很高的技术含量的。至于有多高,两层楼那么高吧。

灰度图只有亮度信息而没有颜色信息,这种特性使得它在在图像处理领域中应用非常广泛,包括:

  • 去除颜色影响后,灰度图像可以更容易地反应图像的纹理、边缘。比如医学领域里的X光、CT影像图片。
  • 灰度图每个点就256个维度,而BGR图每个点有256 * 256 * 256 = 16777216个维度,寻找特征时计算量太大了。
  • 相比彩色图像,减少了三分之二的存储空间。

一般来说,为了寻找特征,转换完成灰度图后,接下来会紧跟着下一步:二值化。那什么是二值化,二值化怎么转换,二值化后又有什么好处呢。下一篇将详细举例。

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

  • 36
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值