前面的文章,咱们简单的介绍了常用的定位工具,包括多种模板匹配以及直线圆弧等卡尺工具;今天咱们一起探讨下视觉中常用的图像前处理工具(二值化,灰度形态学,滤波,图像增强,频域变换等);因为篇幅原因,就先聊聊opencv中灰度形态学的功能和使用方法,有不足之处大家可以在评论处留言,大家共同学习共同进步!
1. 灰度膨胀(Grayscale Dilation)运算
先看一组测试效果图:
图1) 图2)
图1) 为原图;
图2) 为膨胀后效果图。
实现代码如下:
if (obj is gray_dilation_rect)//膨胀
{
int _width = (obj as gray_dilation_rect).MarkWidth;
int _height = (obj as gray_dilation_rect).MarkHeight;
temimage= Morphological_Proces.DilateImage(imageBuffer,
MorphShapes.Rect,new OpenCvSharp.Size (_width, _height));
Cv2.CopyTo(temimage, imageBuffer);
temimage.Dispose();
temimage = null;
}
/// <summary>
/// 图像膨胀:
/// 对图片的高亮度部分(白色)进行操作,膨胀是对高亮度部分进行"领域扩张"
/// </summary>
/// <param name="src">输入图像</param>
/// <param name="morphShape">结构元素类型</param>
/// <param name="kernelSize">内核尺寸</param>
/// <param name="iterations">迭代次数</param>
/// <returns>返回膨胀后的图像</returns>
static public Mat DilateImage(Mat src, MorphShapes morphShape, Size kernelSize, int iterations = 1)
{
if (src.Empty())
return null;
Mat dst = new Mat();
Mat element = Cv2.GetStructuringElement(morphShape, kernelSize, new CVPoint(-1, -1));
/*膨胀dilate:
* src:输入图像(建议二值图)
* dst:输出图像
* element:用于膨胀的结构单元。如果element=new Mat()[为空的意思],则使用一个3x3的矩形结构单元
* anchor :锚点位置,默认为(-1,-1)表示位于中心
* iterations :膨胀次数
* borderType :边界模式,一般使用默认值
* borderValue :边界值,一般采用默认值
*/
Cv2.Dilate(src, dst, element, new CVPoint(-1, -1), iterations);
return dst;
}
灰度膨胀的效果
观察以上灰度膨胀效果图,可以看出灰度膨胀具有如下效果:
-
灰度膨胀能够使得灰度图像中,被暗区包围的亮区,区域变大,而被亮区包围的暗区,区域变小(可以简单地理解为,黑色中的白色区域面接增大,白色区域中的黑色,面积变得更小)。
-
由于膨胀运算,灰度图像中一些较小的黑色的点(灰度值小),会被灰度值更大的灰度覆盖(填充)。
-
灰度膨胀对一些灰度变化更为强烈的区域效果更明显,即灰度变化率更大的区域,灰度膨胀的效果更明显。
2. 灰度腐蚀(Grayscale Erode)运算
测试效果图如下:
图3) 图4)
图3) 为原图;
图4) 为腐蚀后效果图。
实现代码如下:
else if (obj is gray_erosion_rect)//腐蚀
{
int _width = (obj as gray_erosion_rect).MarkWidth;
int _height = (obj as gray_erosion_rect).MarkHeight;
temimage = Morphological_Proces.ErodeImage(imageBuffer,
MorphShapes.Rect, new OpenCvSharp.Size(_width, _height));
Cv2.CopyTo(temimage, imageBuffer);
temimage.Dispose();
temimage = null;
}
/// <summary>
/// 图像腐蚀:
/// 对图片的高亮度部分(白色)进行操作,腐蚀是对高亮度部分进行"领域蚕食""
/// </summary>
/// <param name="src">输入原图</param>
/// <param name="morphShape">结构元素</param>
/// <param name="kernelSize">内核尺寸</param>
/// <param name="iterations">迭代次数</param>
/// <returns></returns>
static public Mat ErodeImage(Mat src, MorphShapes morphShape, Size kernelSize, int iterations = 1)
{
if (src.Empty())
return null;
Mat dst = new Mat();
Mat element = Cv2.GetStructuringElement(morphShape, kernelSize, new CVPoint(-1, -1));
/*腐蚀erode:
* src:输入图像(建议二值图)
* dst:输出图像
* element:用于腐蚀的结构单元。如果element=new Mat()[为空的意思],则使用一个3x3的矩形结构单元
* anchor :锚点位置,默认为(-1,-1)表示位于中心
* iterations :腐蚀次数
* borderType :边界模式,一般使用默认值
* borderValue :边界值,一般采用默认值
*/
Cv2.Erode(src, dst, element, new CVPoint(-1, -1), iterations);
return dst;
}
灰度腐蚀的特征
灰度腐蚀的效果,与灰度膨胀来对比,呈现出相反的特征,具体特征如下:
- 原始图像中,被暗色域包围的亮色域的区域大小会收缩,而被亮色域包围的暗色域的区域大小会扩张;
- 图像中一些较小的亮点会消失,而一些小的暗点会变大(可以认为,灰度具有让图像灰度值变小的效果,所以,灰度较大的白色会趋于消失,而灰度较小的黑色的尺寸会趋于增大。)
- 与灰度膨胀一样,灰度腐蚀的效果在图像灰度变化剧烈(图像梯度更大)的区域更明显。
3. 灰度开运算
测试效果图如下:
图5) 图6)
图5) 为原图;
图6) 为开运算效果图。
实现代码如下:
else if (obj is gray_opening_rect)//开运算
{
int _width = (obj as gray_opening_rect).MarkWidth;
int _height = (obj as gray_opening_rect).MarkHeight;
temimage = Morphological_Proces.MorphologyEx(imageBuffer, MorphShapes.Rect,
new OpenCvSharp.Size(_width, _height), MorphTypes.Open);
Cv2.CopyTo(temimage, imageBuffer);
temimage.Dispose();
temimage = null;
}
/// <summary>
/// 形态学处理
/// </summary>
/// <param name="src">输入原图</param>
/// <param name="morphShape">形态结构元素</param>
/// <param name="kernelSize">内核尺寸</param>
/// <param name="morphType">形态操作类型</param>
/// <param name="iterations">迭代次数</param>
/// <returns></returns>
static public Mat MorphologyEx(Mat src, MorphShapes morphShape, Size kernelSize,
MorphTypes morphType, int iterations = 1)
{
if (src.Empty())
return null;
Mat dst = new Mat();
Mat element = Cv2.GetStructuringElement(morphShape, kernelSize, new CVPoint(-1, -1));
/*腐蚀:对高亮度部分进行"领域蚕食""
* 膨胀:对高亮度部分进行"领域扩张"
* 开运算:先腐蚀,后膨胀的过程,可以去掉小的对象
* 闭运算:先膨后腐蚀的顺序 ,可以填充图像中细小的空洞
* 形态学梯度:用膨胀图减去腐蚀图,可以将图像边缘凸现出来,可以用其来保留边缘轮廓
* 顶帽:源图像与开运算的图像相减,用来分离比领近点亮一些的斑块
* 黑帽:闭运算图像与源图像做差,用来分离比领近点暗一些的斑块
* 击中击不中:击中击不中变换是形态学中用来检测特定形状所处位置的一个基本工具。它的原理就是使用腐蚀,
* 如果要在一幅图像A上找到B形状的目标
*/
Cv2.MorphologyEx(src, dst, morphType, element, new CVPoint(-1, -1), iterations);
return dst;
}
灰度开运算的特点
综合以上两个实例,可以看出,灰度开运算具有如下特点:
- 对于一副灰度图像而言,如果一副图像中亮色(像素值较高)区域的尺寸比结构化元素的尺寸小,则会被抹去。
4. 灰度闭运算
测试效果图如下:
图7) 图8)
图7) 为原图;
图8) 为闭运算效果图。
实现代码如下:
else if (obj is gray_closing_rect)//闭运算
{
int _width = (obj as gray_closing_rect).MarkWidth;
int _height = (obj as gray_closing_rect).MarkHeight;
temimage = Morphological_Proces.MorphologyEx(imageBuffer, MorphShapes.Rect,
new OpenCvSharp.Size(_width, _height), MorphTypes.Close);
Cv2.CopyTo(temimage, imageBuffer);
temimage.Dispose();
temimage = null;
}
/// <summary>
/// 形态学处理
/// </summary>
/// <param name="src">输入原图</param>
/// <param name="morphShape">形态结构元素</param>
/// <param name="kernelSize">内核尺寸</param>
/// <param name="morphType">形态操作类型</param>
/// <param name="iterations">迭代次数</param>
/// <returns></returns>
static public Mat MorphologyEx(Mat src, MorphShapes morphShape, Size kernelSize,
MorphTypes morphType, int iterations = 1)
{
if (src.Empty())
return null;
Mat dst = new Mat();
Mat element = Cv2.GetStructuringElement(morphShape, kernelSize, new CVPoint(-1, -1));
/*腐蚀:对高亮度部分进行"领域蚕食""
* 膨胀:对高亮度部分进行"领域扩张"
* 开运算:先腐蚀,后膨胀的过程,可以去掉小的对象
* 闭运算:先膨后腐蚀的顺序 ,可以填充图像中细小的空洞
* 形态学梯度:用膨胀图减去腐蚀图,可以将图像边缘凸现出来,可以用其来保留边缘轮廓
* 顶帽:源图像与开运算的图像相减,用来分离比领近点亮一些的斑块
* 黑帽:闭运算图像与源图像做差,用来分离比领近点暗一些的斑块
* 击中击不中:击中击不中变换是形态学中用来检测特定形状所处位置的一个基本工具。它的原理就是使用腐蚀,
* 如果要在一幅图像A上找到B形状的目标
*/
Cv2.MorphologyEx(src, dst, morphType, element, new CVPoint(-1, -1), iterations);
return dst;
}
灰度闭运算的效果
通过以上分析,灰度闭运算具有如下效果:
-
如果一副图像中,被暗色区域包围的亮色区域的尺寸小于结构化元素的尺寸,则灰度闭运算会使得该亮色区域的亮度增强。
-
如果,灰度开运算结构化元素的尺寸越大,对原始图像的影响也越大,即原始图像中亮色增强的区域也越大。
总结:
以上简单介绍了opencv中有关灰度形态学的部分功能,后面文章将介绍图像前处理面的其它工具,如果大家感兴趣可以一起探讨学习;所有前面文章中介绍的功能的源码地址如下:
OPENCV+C#+C++开发资源及源码分享_%Onmyway的博客-CSDN博客
PS:成功就是每天进步一点点!