版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
教程VB.net版本请访问:EmguCV学习笔记 VB.Net 目录-CSDN博客
教程C#版本请访问:EmguCV学习笔记 C# 目录-CSDN博客
笔者的博客网址:https://blog.csdn.net/uruseibest
教程配套文件及相关说明以及如何获得pdf教程和代码(博客上的教程内容会和pdf教程一致,教程中也会包含所有代码),请移步:EmguCV学习笔记
4.2 二值化
4.2.1 Threshold
Threshold方法用于对图像进行二值化处理,将图像中的像素值转换为0或255,以便于后续的图像分割、形状检测等处理。该方法只能处理灰度图像,如果要对彩色图像进行二值化处理,需要先将其转换为灰度图像。此外,在使用Threshold方法时,还需要根据实际情况选择不同的二值化操作类型,以达到最佳的处理效果。
Threshold的声明如下:
public static double Threshold(
IInputArray src,
IOutputArray dst,
double threshold,
double maxValue,
ThresholdType thresholdType
)
参数说明:
- src:原始图像,通常是Mat类型。
- dst:输出图像,通常是Mat类型。
- thresh:阈值,Double类型。
- maxval:最大值,Double类型,在二值化操作中,将大于阈值的像素值设为该值。
- type:二值化操作的类型,ThresholdType类型,包括以下常量:
- Binary:二值化操作,将大于阈值的像素值设为maxval,小于等于阈值的像素值设为0。
- BinaryInv:反向二值化操作,将小于等于阈值的像素值设为maxval,大于阈值的像素值设为0。
- Trunc:截断操作,将大于阈值的像素值设为阈值,小于等于阈值的像素值不变。
- ToZero:零值操作,将小于等于阈值的像素值设为0,大于阈值的像素值不变。
- ToZeroInv:反向零值操作,将大于阈值的像素值设为0,小于等于阈值的像素值不变。
- Otsu:使用大津法,通过分析图像的灰度直方图,自动确定最佳的阈值,从而实现二值化,可以适用于大部分图像的二值化处理。如果使用了此类型,那么thresh参数将忽略。
- Triangle:使用Triangle算法,通过寻找直方图中的三角形区域,自动确定最佳的阈值,从而实现二值化。如果使用了此类型,那么thresh参数将忽略。
返回值:
返回ThresholdType为Otsu 或Triangle时,确定的最佳阈值(threshold的参数的值);如果ThresholdType不是Otsu 或Triangle,那么就返回设定的阈值。
【代码位置:frmChapter4】Button2_Click
//Threshold
private void Button2_Click(object sender, EventArgs e)
{
//可以直接使用ImreadModes.Grayscale,这里为了直观对比使用彩色图像
Mat m = new Mat("C:\\learnEmgucv\\lena.jpg", ImreadModes.Color);
ImageBox1.Image = m;
//灰度转换
Mat mgray = new Mat();
CvInvoke.CvtColor(m, mgray, ColorConversion.Bgr2Gray);
Mat mOut1 = new Mat();
//使用Binary类型进行二值化
CvInvoke.Threshold(mgray, mOut1, 125, 255, ThresholdType.Binary);
ImageBox2.Image = mOut1;
Mat mOut2 = new Mat();
Double thresh;
//使用大律法自动确定阈值进行二值化,并返回使用Otsu计算出的阈值
thresh = CvInvoke.Threshold(mgray, mOut2, 0, 255, ThresholdType.Otsu);
ImageBox3.Image = mOut2;
}
运行后如下图所示:
图4-3 图像二值化
4.2.2 AdaptiveThreshold
AdaptiveThreshold方法用于对图像进行自适应阈值处理,将图像中的像素值转换为0或255,以便于后续的图像分割、形状检测等处理。该方法只能处理灰度图像,如果要对彩色图像进行自适应阈值处理,需要先将其转换为灰度图像。
AdaptiveThreshold方法的声明如下:
public static void AdaptiveThreshold(
IInputArray src,
IOutputArray dst,
double maxValue,
AdaptiveThresholdType adaptiveType,
ThresholdType thresholdType,
int blockSize,
double param1
)
主要参数说明:
- maxValue:最大值,Double类型,在二值化操作中,将大于阈值的像素值设为该值。
- adaptiveMethod:自适应阈值处理的方法,AdaptiveThresholdTyp类型,包括以下常量:
- MeanC:阈值为邻域内的均值减去一个常数(param1)。
- GaussianC:阈值为邻域内的高斯加权平均值减去一个常数(param1)。
- thresholdType:二值化操作的类型,只能是ThresholdType类型的Binary或者BinaryInv。
- blockSize:邻域大小,必须为大于3的奇数。
- param1:常数,Double类型,表示从均值或高斯加权均值中减去的常数。
【代码位置:frmChapter4】Button3_Click
//AdaptiveThreshold
private void Button3_Click(object sender, EventArgs e)
{
Mat m = new Mat("C:\\learnEmgucv\\lena.jpg", ImreadModes.Color);
ImageBox1.Image = m;
//彩色转为灰度
Mat mgray = new Mat();
CvInvoke.CvtColor(m, mgray, ColorConversion.Bgr2Gray);
Mat mOut1 = new Mat();
//使用高斯加权平均值进行二值化
CvInvoke.AdaptiveThreshold(mgray, mOut1, 255, AdaptiveThresholdType.GaussianC, ThresholdType.Binary, 3, 0);
ImageBox2.Image = mOut1;
Mat mOut2 = new Mat();
//使用均值进行二值化
CvInvoke.AdaptiveThreshold(mgray, mOut2, 255, AdaptiveThresholdType.MeanC, ThresholdType.Binary, 3, 0);
ImageBox3.Image = mOut2;
}
运行后如下图所示:
图4-4 使用AdaptiveThreshold进行图像二值化
4.2.3 图像通道分离和合并
图像通道的分离和合并分别使用到了CvInvoke的Split和Merge方法。Merge方法在2.3.11节【图像通道的分离与合并】有介绍,而CvInvoke.Split方法和该节的Mat.Split方法有所区别,详细请看代码说明。
【代码位置:frmChapter4】Button4_Click
//通道分离和合并
private void Button4_Click(object sender, EventArgs e)
{
Mat m = new Mat("C:\\learnEmgucv\\lena.jpg", ImreadModes.Color);
ImageBox1.Image = m;
//将图像通道分离到 VectorOfMat
VectorOfMat vom = new VectorOfMat();
CvInvoke.Split(m, vom);
Mat mOut1 = new Mat();
//输出分离后的第一个通道
mOut1 = vom[0];
ImageBox2.Image = mOut1;
//注意和CvInvoke.Split的对比
Mat[] channels = m.Split();
//对三个通道分别进行二值化
CvInvoke.Threshold(channels[0], channels[0], 100, 255, Emgu.CV.CvEnum.ThresholdType.Binary);
CvInvoke.Threshold(channels[1], channels[0], 100, 255, Emgu.CV.CvEnum.ThresholdType.Binary);
CvInvoke.Threshold(channels[2], channels[0], 100, 255, Emgu.CV.CvEnum.ThresholdType.Binary);
//将处理后的三个通道推入 VectorOfMat
VectorOfMat newm = new VectorOfMat();
newm.Push(channels[0]);
newm.Push(channels[1]);
newm.Push(channels[2]);
Mat mdst = new Mat();
//合并通道
CvInvoke.Merge(newm, mdst);
ImageBox3.Image = mdst;
}
运行后如下图所示:
图4-5 图像通道的分离和合并
4.2.4 按颜色分离
CvInvoke.InRange方法用于在图像中找到指定范围内的像素,并将其设置为白色,其余的像素设置为黑色。在使用CvInvoke.InRange方法时,需要根据实际情况选择合适的下限和上限,以达到最佳的处理效果。同时,CvInvoke.InRange方法只能处理单通道和三通道的图像。如果图像通道数不为1或3,需要先将其转换为单通道或三通道图像。
InRange方法的声明如下:
public static void InRange(
IInputArray src,
IInputArray lower,
IInputArray upper,
IOutputArray dst
)
主要参数说明:
lowerb参数是指定范围的下限。
upperb参数是指定范围的上限。
【代码位置:frmChapter4】Button5_Click
//颜色分离
private void Button5_Click(object sender, EventArgs e)
{
Mat m = new Mat("C:\\learnEmgucv\\wslt.jpg", ImreadModes.Color);
ImageBox1.Image = m;
Mat hsv = new Mat();
//转为Hsv,更容易分离颜色
CvInvoke.CvtColor(m, hsv, ColorConversion.Bgr2Hsv);
//设置颜色范围下限和上限,需要根据实际慢慢修改
ScalarArray lowerb1 = new ScalarArray(new MCvScalar(0, 10, 180));
ScalarArray upperb1 = new ScalarArray(new MCvScalar(50, 160, 255));
Mat dst = new Mat();
//使用InRange分离颜色,返回二值图
CvInvoke.InRange(hsv, lowerb1, upperb1, dst);
ImageBox2.Image = dst;
Mat dstchannel3 = new Mat();
//转为3通道图像
CvInvoke.CvtColor(dst, dstchannel3, ColorConversion.Gray2Bgr);
Mat result = new Mat();
//做And运算,然后显示分离结果
CvInvoke.BitwiseAnd(m, dstchannel3, result);
ImageBox3.Image = result;
}
运行后如下图所示:
图4-6 InRange方法分离出人脸